diff options
author | lloyd <[email protected]> | 2009-10-28 22:55:12 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-10-28 22:55:12 +0000 |
commit | 3623be3fd05d890309cc3da4b3a1e319e357df65 (patch) | |
tree | 34ca43fcf8a7007cc01a3919f63e9ab6763cb673 | |
parent | fc1e61500e77fcabe67e6d2607810c1ba071bbdd (diff) | |
parent | 9462f875b13a321f42a127166d49670ca04afcde (diff) |
propagate from branch 'net.randombit.botan.1_8' (head 3158f8272a3582dd44dfb771665eb71f7d005339)
to branch 'net.randombit.botan' (head bf629b13dd132b263e76a72b7eca0f7e4ab19aac)
393 files changed, 12111 insertions, 6047 deletions
diff --git a/.mtn-ignore b/.mtn-ignore index 63acd11e3..9472cff88 100644 --- a/.mtn-ignore +++ b/.mtn-ignore @@ -1,4 +1,4 @@ -^Makefile$ +^Makefile.*$ ^botan-config$ ^botan.pc$ ^build$ @@ -22,3 +22,6 @@ callgrind.out.* ^doc/.*\.log$ ^doc/.*\.toc$ ^doc/examples/.*\.pem$ +^src/wrap/perl-xs/Botan.(bs|c)$ +^src/wrap/perl-xs/Makefile(\.old)?$ +^src/wrap/perl-xs/.*blib$ diff --git a/checks/algos.cpp b/checks/algos.cpp deleted file mode 100644 index 2edaaf14c..000000000 --- a/checks/algos.cpp +++ /dev/null @@ -1,105 +0,0 @@ - -#include <botan/botan.h> -#include <string> -using namespace Botan; - -#include "common.h" - -std::vector<algorithm> get_algos() - { - std::vector<algorithm> algos; - - algos.push_back(algorithm("Block Cipher", "AES-128", "AES-128/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "AES-192", "AES-192/ECB", 24)); - algos.push_back(algorithm("Block Cipher", "AES-256", "AES-256/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "Blowfish", "Blowfish/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "CAST-128", "CAST-128/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "CAST-256", "CAST-256/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "DES", "DES/ECB", 8)); - algos.push_back(algorithm("Block Cipher", "DESX", "DESX/ECB", 24)); - algos.push_back(algorithm("Block Cipher", "TripleDES", - "TripleDES/ECB", 24)); - algos.push_back(algorithm("Block Cipher", "GOST", "GOST/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "IDEA", "IDEA/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "KASUMI", "KASUMI/ECB", 16)); - - algos.push_back(algorithm("Block Cipher", - "Lion", - "Lion(SHA-256,Turing,8192)/ECB", 32)); - - algos.push_back(algorithm("Block Cipher", "Luby-Rackoff(SHA-512)", - "Luby-Rackoff(SHA-512)/ECB", 16)); - - algos.push_back(algorithm("Block Cipher", "MARS", "MARS/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "MISTY1", "MISTY1/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "Noekeon", "Noekeon/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "RC2", "RC2/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "RC5(12)", "RC5(12)/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "RC5(16)", "RC5(16)/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "RC6", "RC6/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "SAFER-SK(10)", - "SAFER-SK(10)/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "SEED", "SEED/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "Serpent", "Serpent/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "Skipjack", "Skipjack/ECB", 10)); - algos.push_back(algorithm("Block Cipher", "Square", "Square/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "TEA", "TEA/ECB", 16)); - algos.push_back(algorithm("Block Cipher", "Twofish", "Twofish/ECB", 32)); - algos.push_back(algorithm("Block Cipher", "XTEA", "XTEA/ECB", 16)); - - algos.push_back(algorithm("Cipher Mode", "DES/CBC/PKCS7", 8, 8)); - algos.push_back(algorithm("Cipher Mode", "TripleDES/CBC/PKCS7", 24, 8)); - - algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/PKCS7", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CBC/CTS", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(128)", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(64)", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(32)", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(16)", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CFB(8)", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/OFB", 16, 16)); - algos.push_back(algorithm("Cipher Mode", "AES-128/CTR", - "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("Stream Cipher", "ARC4", 16)); - algos.push_back(algorithm("Stream Cipher", "Salsa20", 32)); - algos.push_back(algorithm("Stream Cipher", "Turing", 32)); - algos.push_back(algorithm("Stream Cipher", "WiderWake4+1", - "WiderWake4+1-BE", 16, 8)); - - algos.push_back(algorithm("Hash", "Adler32")); - algos.push_back(algorithm("Hash", "CRC24")); - algos.push_back(algorithm("Hash", "CRC32")); - algos.push_back(algorithm("Hash", "FORK-256")); - algos.push_back(algorithm("Hash", "GOST-34.11")); - algos.push_back(algorithm("Hash", "HAS-160")); - algos.push_back(algorithm("Hash", "HAS-V")); - algos.push_back(algorithm("Hash", "MD2")); - algos.push_back(algorithm("Hash", "MD4")); - algos.push_back(algorithm("Hash", "MD5")); - algos.push_back(algorithm("Hash", "RIPEMD-128")); - algos.push_back(algorithm("Hash", "RIPEMD-160")); - algos.push_back(algorithm("Hash", "SHA-160")); - algos.push_back(algorithm("Hash", "SHA-256")); - algos.push_back(algorithm("Hash", "SHA-384")); - algos.push_back(algorithm("Hash", "SHA-512")); - algos.push_back(algorithm("Hash", "Skein-512")); - algos.push_back(algorithm("Hash", "Tiger")); - algos.push_back(algorithm("Hash", "Whirlpool")); - - algos.push_back(algorithm("MAC", "CMAC(AES-128)", 16)); - algos.push_back(algorithm("MAC", "HMAC(SHA-1)", 16)); - algos.push_back(algorithm("MAC", "X9.19-MAC", 16)); - - algos.push_back(algorithm("RNG", "AutoSeeded", 4096)); - algos.push_back(algorithm("RNG", "HMAC_RNG", 4096)); - algos.push_back(algorithm("RNG", "Randpool", 4096)); - algos.push_back(algorithm("RNG", "X9.31-RNG", 4096)); - - algos.push_back(algorithm("Codec", "Base64_Encode")); - algos.push_back(algorithm("Codec", "Base64_Decode")); - - return algos; - } diff --git a/checks/bench.cpp b/checks/bench.cpp index 6df7319c0..f821e04e3 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -1,198 +1,230 @@ #include <iostream> #include <iomanip> -#include <cmath> -#include <string> -#include <exception> +#include <botan/benchmark.h> +#include <botan/libstate.h> +#include <botan/pipe.h> #include <botan/filters.h> -using Botan::byte; -using Botan::u64bit; +#include <botan/engine.h> +#include <botan/parsing.h> +#include <botan/symkey.h> #include "common.h" -#include "timer.h" #include "bench.h" -/* Discard output to reduce overhead */ -struct BitBucket : public Botan::Filter - { - void write(const byte[], u32bit) {} - }; - -Botan::Filter* lookup(const std::string&, - const std::vector<std::string>&, - const std::string& = "All"); - namespace { -double bench_filter(std::string name, Botan::Filter* filter, - Botan::RandomNumberGenerator& rng, - bool html, double seconds) +const std::string algos[] = { + + /* Block ciphers */ + "AES-128", + "AES-192", + "AES-256", + "Blowfish", + "CAST-128", + "CAST-256", + "DES", + "DESX", + "GOST", + "IDEA", + "KASUMI", + "Lion(SHA-256,Turing,8192)", + "Luby-Rackoff(SHA-512)", + "MARS", + "MISTY1", + "Noekeon", + "RC2", + "RC5(12)", + "RC5(16)", + "RC6", + "SAFER-SK(10)", + "SEED", + "Serpent", + "Skipjack", + "Square", + "TEA", + "TripleDES", + "Twofish", + "XTEA", + + /* Cipher modes */ + "TripleDES/CBC/PKCS7", + "TripleDES/CBC/CTS", + "TripleDES/CTR-BE", + "TripleDES/EAX", + "TripleDES/OFB", + "TripleDES/CFB(64)", + "TripleDES/CFB(32)", + "TripleDES/CFB(16)", + "TripleDES/CFB(8)", + + "AES-128/CBC/PKCS7", + "AES-128/CBC/CTS", + "AES-128/CTR-BE", + "AES-128/EAX", + "AES-128/OFB", + "AES-128/XTS", + "AES-128/CFB(128)", + "AES-128/CFB(64)", + "AES-128/CFB(32)", + "AES-128/CFB(16)", + "AES-128/CFB(8)", + + "Serpent/CBC/PKCS7", + "Serpent/CBC/CTS", + "Serpent/CTR-BE", + "Serpent/EAX", + "Serpent/OFB", + "Serpent/XTS", + "Serpent/CFB(128)", + "Serpent/CFB(64)", + "Serpent/CFB(32)", + "Serpent/CFB(16)", + "Serpent/CFB(8)", + + /* Stream ciphers */ + "ARC4", + "Salsa20", + "Turing", + "WiderWake4+1-BE", + + /* Checksums */ + "Adler32", + "CRC24", + "CRC32", + + /* Hashes */ + "BMW-512", + "FORK-256", + "GOST-34.11", + "HAS-160", + "MD2", + "MD4", + "MD5", + "RIPEMD-128", + "RIPEMD-160", + "SHA-160", + "SHA-256", + "SHA-384", + "SHA-512", + "Skein-512", + "Tiger", + "Whirlpool", + + /* MACs */ + "CMAC(AES-128)", + "HMAC(SHA-1)", + "X9.19-MAC", + "", +}; + +void report_results(const std::string& algo, + const std::map<std::string, double>& speeds) { - Botan::Pipe pipe(filter, new BitBucket); - - std::vector<byte> buf(128 * 1024); - rng.randomize(&buf[0], buf.size()); - - pipe.start_msg(); - - Timer timer(name, buf.size()); + // invert, showing fastest impl first + std::map<double, std::string> results; - while(timer.seconds() < seconds) + for(std::map<std::string, double>::const_iterator i = speeds.begin(); + i != speeds.end(); ++i) { - timer.start(); - pipe.write(&buf[0], buf.size()); - timer.stop(); + // Speeds might collide, tweak slightly to handle this + if(results[i->second] == "") + results[i->second] = i->first; + else + results[i->second - .01] = i->first; } - pipe.end_msg(); + std::cout << algo; - double bytes_per_sec = timer.events() / timer.seconds(); - double mbytes_per_sec = bytes_per_sec / (1024.0 * 1024.0); - - 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, "<"); - if(name.find(">") != std::string::npos) - name.replace(name.find(">"), 1, ">"); - std::cout << " <TR><TH>" << name - << std::string(25 - name.length(), ' ') << " <TH>"; - std::cout.width(6); - std::cout << mbytes_per_sec << std::endl; - } - else + for(std::map<double, std::string>::const_reverse_iterator i = results.rbegin(); + i != results.rend(); ++i) { - std::cout << name << ": " << std::string(25 - name.length(), ' '); - std::cout.width(6); - std::cout << mbytes_per_sec << " MiB/sec" << std::endl; + std::cout << " [" << i->second << "] " + << std::fixed << std::setprecision(2) << i->first; } - return (mbytes_per_sec); + std::cout << "\n"; } -double bench(const std::string& name, const std::string& filtername, bool html, - double seconds, u32bit keylen, u32bit ivlen, - Botan::RandomNumberGenerator& rng) +} + +bool bench_algo(const std::string& algo, + Botan::RandomNumberGenerator& rng, + double seconds) { - std::vector<std::string> params; + Botan::Default_Benchmark_Timer timer; + Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); - Botan::SecureVector<byte> key(keylen); - rng.randomize(key, key.size()); - params.push_back(hex_encode(key, key.size())); + u32bit milliseconds = static_cast<u32bit>(seconds * 1000); - //params.push_back(std::string(int(2*keylen), 'A')); - params.push_back(std::string(int(2* ivlen), 'A')); + std::map<std::string, double> speeds = + algorithm_benchmark(algo, milliseconds, timer, rng, af); - Botan::Filter* filter = lookup(filtername, params); + if(speeds.empty()) // maybe a cipher mode, then? + { + Botan::Algorithm_Factory::Engine_Iterator i(af); - if(filter) - return bench_filter(name, filter, rng, html, seconds); - return 0; - } + std::vector<std::string> algo_parts = Botan::split_on(algo, '/'); -} + if(algo_parts.size() < 2) // not a cipher mode + return false; -void benchmark(const std::string& what, - Botan::RandomNumberGenerator& rng, - bool html, 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"; - } + std::string cipher = algo_parts[0]; - double sum = 0; - u32bit how_many = 0; + u32bit cipher_keylen = + af.prototype_block_cipher(cipher)->MAXIMUM_KEYLENGTH; + u32bit cipher_ivlen = + af.prototype_block_cipher(cipher)->BLOCK_SIZE; - std::vector<algorithm> algos = get_algos(); + if(algo_parts[1] == "XTS") + cipher_keylen *= 2; // hack! - for(u32bit j = 0; j != algos.size(); j++) - if(what == "All" || what == algos[j].type) - { - double speed = bench(algos[j].name, algos[j].filtername, - html, seconds, algos[j].keylen, - algos[j].ivlen, rng); - if(speed > .00001) /* log(0) == -inf -> messed up average */ - sum += std::log(speed); - how_many++; - } + std::vector<byte> buf(16 * 1024); + rng.randomize(&buf[0], buf.size()); - if(html) - std::cout << "</TABLE>\n\n"; + while(Botan::Engine* engine = i.next()) + { + u64bit nanoseconds_max = static_cast<u64bit>(seconds * 1000000000.0); - double average = std::exp(sum / static_cast<double>(how_many)); + Botan::Keyed_Filter* filt = + engine->get_cipher(algo, Botan::ENCRYPTION, af); - if(what == "All" && html) - std::cout << "\n<P>Overall speed average: " << average - << "\n\n"; - else if(what == "All") - std::cout << "\nOverall speed average: " << average - << std::endl; + if(!filt) + continue; - if(html) std::cout << "</BODY></HTML>\n"; - } - catch(Botan::Exception& e) - { - std::cout << "Botan exception caught: " << e.what() << std::endl; - return; - } - catch(std::exception& e) - { - std::cout << "Standard library exception caught: " << e.what() - << std::endl; - return; - } - catch(...) - { - std::cout << "Unknown exception caught." << std::endl; - return; - } - } + filt->set_key(Botan::SymmetricKey(&buf[0], cipher_keylen)); + filt->set_iv(Botan::InitializationVector(&buf[0], cipher_ivlen)); -u32bit bench_algo(const std::string& name, - Botan::RandomNumberGenerator& rng, - double seconds) - { - try { - std::vector<algorithm> algos = get_algos(); + Botan::Pipe pipe(filt, new Botan::BitBucket); + pipe.start_msg(); - for(u32bit j = 0; j != algos.size(); j++) - { - if(algos[j].name == name) + const u64bit start = timer.clock(); + u64bit nanoseconds_used = 0; + u64bit reps = 0; + + while(nanoseconds_used < nanoseconds_max) { - bench(algos[j].name, algos[j].filtername, false, seconds, - algos[j].keylen, algos[j].ivlen, rng); - return 1; + pipe.write(&buf[0], buf.size()); + ++reps; + nanoseconds_used = timer.clock() - start; } + + double mbytes_per_second = + (953.67 * (buf.size() * reps)) / nanoseconds_used; + + speeds[engine->provider_name()] = mbytes_per_second; } - return 0; - } - catch(Botan::Exception& e) - { - std::cout << "Botan exception caught: " << e.what() << std::endl; - return 0; - } - catch(std::exception& e) - { - std::cout << "Standard library exception caught: " << e.what() - << std::endl; - return 0; - } - catch(...) - { - std::cout << "Unknown exception caught." << std::endl; - return 0; } + + if(!speeds.empty()) + report_results(algo, speeds); + + return !speeds.empty(); + } + +void benchmark(Botan::RandomNumberGenerator& rng, + double seconds) + { + for(u32bit i = 0; algos[i] != ""; ++i) + bench_algo(algos[i], rng, seconds); } diff --git a/checks/bench.h b/checks/bench.h index 07d67e0d1..835db0101 100644 --- a/checks/bench.h +++ b/checks/bench.h @@ -1,37 +1,18 @@ -#ifndef BOTAN_BENCHMARCH_H__ -#define BOTAN_BENCHMARCH_H__ +#ifndef BOTAN_CHECK_BENCHMARK_H__ +#define BOTAN_CHECK_BENCHMARK_H__ #include <botan/rng.h> #include <string> -#include <map> -#include <set> -#include "timer.h" -#include <iostream> +void benchmark(Botan::RandomNumberGenerator& rng, + double seconds); -class Benchmark_Report - { - public: - void report(const std::string& name, Timer timer) - { - std::cout << name << " " << timer << std::endl; - data[name].insert(timer); - } - - private: - std::map<std::string, std::set<Timer> > data; - }; - - -void benchmark(const std::string&, Botan::RandomNumberGenerator&, - bool html, double seconds); +bool bench_algo(const std::string& algo_name, + Botan::RandomNumberGenerator& rng, + double seconds); void bench_pk(Botan::RandomNumberGenerator&, - const std::string&, bool html, double seconds); - -u32bit bench_algo(const std::string&, - Botan::RandomNumberGenerator&, - double); + const std::string&, double seconds); #endif diff --git a/checks/check.cpp b/checks/check.cpp index 678cf4b09..b460d34f7 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); @@ -111,9 +111,6 @@ int main(int argc, char* argv[]) << "Options:\n" << " --test || --validate: Run tests (do this at least once)\n" << " --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"; @@ -128,7 +125,7 @@ int main(int argc, char* argv[]) opts.is_set("benchmark") || opts.is_set("bench-type")) { - double seconds = 5; + double seconds = 2; if(opts.is_set("seconds")) { @@ -140,11 +137,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(rng, seconds); } else if(opts.is_set("bench-algo")) { @@ -154,34 +149,10 @@ int main(int argc, char* argv[]) for(u32bit j = 0; j != algs.size(); j++) { 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); + if(!bench_algo(alg, rng, seconds)) // maybe it's a PK algorithm + bench_pk(rng, alg, seconds); } } - else if(opts.is_set("bench-type")) - { - const std::string type = opts.value("bench-type"); - - if(type == "all") - benchmark("All", rng, html, seconds); - else if(type == "block") - benchmark("Block Cipher", rng, html, seconds); - else if(type == "stream") - benchmark("Stream Cipher", rng, html, seconds); - else if(type == "hash") - benchmark("Hash", rng, html, seconds); - else if(type == "mode") - benchmark("Cipher Mode", rng, html, seconds); - else if(type == "mac") - benchmark("MAC", rng, html, seconds); - else if(type == "rng") - benchmark("RNG", rng, html, seconds); - else if(type == "pk") - bench_pk(rng, "All", html, seconds); - else - std::cerr << "Unknown --bench-type " << type << "\n"; - } } } catch(std::exception& e) diff --git a/checks/clock.cpp b/checks/clock.cpp deleted file mode 100644 index e5565ff9c..000000000 --- a/checks/clock.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "timer.h" -#include <botan/build.h> - -/************************************************* -* Platform specific settings for which clock type to use -*/ - -#if !defined(USE_CLOCK_GETTIME) && defined(BOTAN_TARGET_OS_IS_LINUX) - #define USE_GETTIMEOFDAY 1 -#endif - -#if !defined(USE_GETTIMEOFDAY) && defined(BOTAN_TARGET_OS_IS_FREEBSD) - #define USE_GETTIMEOFDAY 1 -#endif - -/************************************************* - Set the default, which is clock -*/ -#ifndef USE_CLOCK_GETTIME - #define USE_CLOCK_GETTIME 0 -#endif - -#ifndef USE_GETTIMEOFDAY - #define USE_GETTIMEOFDAY 0 -#endif - -#ifndef USE_TIMES - #define USE_TIMES 0 -#endif - -/* the default: ANSI/ISO clock */ -#ifndef USE_CLOCK - #define USE_CLOCK 1 -#endif - -#if USE_CLOCK_GETTIME - #include <time.h> -#elif USE_GETTIMEOFDAY - #include <sys/time.h> -#elif USE_TIMES - #include <sys/times.h> - #include <unistd.h> -#elif USE_CLOCK - #include <time.h> -#endif - -/* The implementation: */ -u64bit Timer::get_clock() - { - static const u64bit billion = 1000000000; - -#if USE_CLOCK_GETTIME - - struct timespec tv; - clock_gettime(CLOCK_REALTIME, &tv); - return (billion * tv.tv_sec + tv.tv_nsec); - -#elif USE_GETTIMEOFDAY - - struct timeval tv; - gettimeofday(&tv, 0); - return (billion * tv.tv_sec + 1000 * tv.tv_usec); - -#elif USE_TIMES - - struct tms tms; - times(&tms); - - static const u64bit clocks_to_nanoseconds = - (billion / sysconf(_SC_CLK_TCK)); - - return (tms.tms_utime * clocks_to_nanoseconds); - -#elif USE_CLOCK - - static const u64bit clocks_to_nanoseconds = - (billion / CLOCKS_PER_SEC); - - return clock() * clocks_to_nanoseconds; - -#endif - } diff --git a/checks/common.h b/checks/common.h index fa41882ee..5b8f0a5d0 100644 --- a/checks/common.h +++ b/checks/common.h @@ -14,20 +14,7 @@ using Botan::byte; using Botan::u32bit; - -struct algorithm - { - algorithm(const char* t, const char* n, - u32bit k = 0, u32bit i = 0) : - type(t), name(n), filtername(n), keylen(k), ivlen(i) {} - algorithm(const char* t, const char* n, - const char* f, u32bit k = 0, u32bit i = 0) : - type(t), name(n), filtername(f), keylen(k), ivlen(i) {} - std::string type, name, filtername; - u32bit keylen, ivlen, weight; - }; - -std::vector<algorithm> get_algos(); +using Botan::u64bit; void strip_comments(std::string& line); void strip_newlines(std::string& line); diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp index 792e9c58d..d62099b6e 100644 --- a/checks/cvc_tests.cpp +++ b/checks/cvc_tests.cpp @@ -27,7 +27,7 @@ #include <botan/look_pk.h> #include <botan/cvc_self.h> #include <botan/cvc_cert.h> -#include <botan/util.h> +#include <botan/timer.h> #include <botan/cvc_ado.h> #define TEST_DATA_DIR "checks/ecc_testdata" diff --git a/checks/dolook.cpp b/checks/dolook.cpp index 0c20448af..b64c5a5a3 100644 --- a/checks/dolook.cpp +++ b/checks/dolook.cpp @@ -4,6 +4,11 @@ #include <botan/lookup.h> #include <botan/filters.h> #include <botan/libstate.h> +#include <botan/hmac.h> +#include <botan/aes.h> +#include <botan/sha2_32.h> +#include <botan/sha2_64.h> +#include <botan/parsing.h> #ifdef BOTAN_HAS_COMPRESSOR_BZIP2 #include <botan/bzip2.h> @@ -17,84 +22,203 @@ #include <botan/zlib.h> #endif +#if defined(BOTAN_HAS_RANDPOOL) + #include <botan/randpool.h> +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + #include <botan/hmac_rng.h> +#endif + +#if defined(BOTAN_HAS_X931_RNG) + #include <botan/x931_rng.h> + #include <botan/des.h> +#endif + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include <botan/auto_rng.h> +#endif + using namespace Botan; #include "common.h" -Filter* lookup(const std::string& algname, - const std::vector<std::string>& params, - const std::string& section) +/* A weird little hack to fit S2K algorithms into the validation suite + You probably wouldn't ever want to actually use the S2K algorithms like + this, the raw S2K interface is more convenient for actually using them +*/ +class S2K_Filter : public Filter { - std::string key = params[0]; - std::string iv = params[1]; - Filter* filter = 0; - - // The order of the lookup has to change based on how the names are - // formatted and parsed. - filter = lookup_kdf(algname, key, iv); - if(filter) return filter; + public: + void write(const byte in[], u32bit len) + { passphrase += std::string(reinterpret_cast<const char*>(in), len); } + void end_msg() + { + s2k->change_salt(salt, salt.size()); + s2k->set_iterations(iterations); + SymmetricKey x = s2k->derive_key(outlen, passphrase); + send(x.bits_of()); + } + S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i) + { + s2k = algo; + outlen = o; + iterations = i; + salt = s.bits_of(); - if(section == "Cipher Modes (Decryption)") - filter = lookup_cipher(algname, key, iv, false); - else - filter = lookup_cipher(algname, key, iv, true); - if(filter) return filter; + } + ~S2K_Filter() { delete s2k; } + private: + std::string passphrase; + S2K* s2k; + SecureVector<byte> salt; + u32bit outlen, iterations; + }; - filter = lookup_block(algname, key); - if(filter) return filter; - - filter = lookup_rng(algname, key); - if(filter) return filter; +/* Not too useful generally; just dumps random bits for benchmarking */ +class RNG_Filter : public Filter + { + public: + void write(const byte[], u32bit); - filter = lookup_encoder(algname); - if(filter) return filter; + RNG_Filter(RandomNumberGenerator* r) : rng(r) {} + ~RNG_Filter() { delete rng; } + private: + RandomNumberGenerator* rng; + }; - filter = lookup_hash(algname); - if(filter) return filter; +class KDF_Filter : public Filter + { + public: + void write(const byte in[], u32bit len) + { secret.append(in, len); } + void end_msg() + { + SymmetricKey x = kdf->derive_key(outlen, + secret, secret.size(), + salt, salt.size()); + send(x.bits_of(), x.length()); + } + KDF_Filter(KDF* algo, const SymmetricKey& s, u32bit o) + { + kdf = algo; + outlen = o; + salt = s.bits_of(); + } + ~KDF_Filter() { delete kdf; } + private: + SecureVector<byte> secret; + SecureVector<byte> salt; + KDF* kdf; + u32bit outlen; + }; - filter = lookup_mac(algname, key); - if(filter) return filter; +Filter* lookup_s2k(const std::string& algname, + const std::vector<std::string>& params) + { + S2K* s2k = 0; - filter = lookup_s2k(algname, params); - if(filter) return filter; + try { + s2k = get_s2k(algname); + } + catch(...) { } + if(s2k) + return new S2K_Filter(s2k, params[0], to_u32bit(params[1]), + to_u32bit(params[2])); return 0; } -Filter* lookup_hash(const std::string& algname) +void RNG_Filter::write(const byte[], u32bit length) { - Filter* hash = 0; - - try { - hash = new Hash_Filter(algname); + if(length) + { + SecureVector<byte> out(length); + rng->randomize(out, out.size()); + send(out); } - catch(Algorithm_Not_Found) {} - - return hash; } -Filter* lookup_mac(const std::string& algname, const std::string& key) +Filter* lookup_rng(const std::string& algname, + const std::string& key) { - Filter* mac = 0; - try { - mac = new MAC_Filter(algname, key); + RandomNumberGenerator* prng = 0; + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + if(algname == "AutoSeeded") + prng = new AutoSeeded_RNG; +#endif + +#if defined(BOTAN_HAS_X931_RNG) + if(algname == "X9.31-RNG(TripleDES)") + prng = new ANSI_X931_RNG(new TripleDES, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-128)") + prng = new ANSI_X931_RNG(new AES_128, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-192)") + prng = new ANSI_X931_RNG(new AES_192, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-256)") + prng = new ANSI_X931_RNG(new AES_256, + new Fixed_Output_RNG(decode_hex(key))); +#endif + +#if defined(BOTAN_HAS_RANDPOOL) + if(algname == "Randpool") + { + prng = new Randpool(new AES_256, new HMAC(new SHA_256)); + + prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), + key.length()); + } +#endif + +#if defined(BOTAN_HAS_X931_RNG) + // these are used for benchmarking: AES-256/SHA-256 matches library + // defaults, so benchmark reflects real-world performance (maybe) + if(algname == "X9.31-RNG") + { + RandomNumberGenerator* rng = +#if defined(BOTAN_HAS_HMAC_RNG) + new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); +#elif defined(BOTAN_HAS_RANDPOOL) + new Randpool(new AES_256, new HMAC(new SHA_256)); +#endif + + prng = new ANSI_X931_RNG(new AES_256, rng); + + } +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + if(algname == "HMAC_RNG") + { + prng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); } - catch(Algorithm_Not_Found) {} +#endif - return mac; + if(prng) + { + prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), + key.length()); + return new RNG_Filter(prng); + } + + return 0; } -Filter* lookup_cipher(const std::string& algname, const std::string& key, - const std::string& iv, bool encrypt) +Filter* lookup_kdf(const std::string& algname, const std::string& salt, + const std::string& params) { + KDF* kdf = 0; try { - if(encrypt) - return get_cipher(algname, key, iv, ENCRYPTION); - else - return get_cipher(algname, key, iv, DECRYPTION); + kdf = get_kdf(algname); } - catch(Algorithm_Not_Found) {} - catch(Invalid_Algorithm_Name) {} + catch(...) { return 0; } + + if(kdf) + return new KDF_Filter(kdf, salt, to_u32bit(params)); return 0; } @@ -128,3 +252,28 @@ Filter* lookup_encoder(const std::string& algname) return 0; } + +Filter* lookup(const std::string& algname, + const std::vector<std::string>& params) + { + std::string key = params[0]; + std::string iv = params[1]; + Filter* filter = 0; + + // The order of the lookup has to change based on how the names are + // formatted and parsed. + filter = lookup_kdf(algname, key, iv); + if(filter) return filter; + + filter = lookup_rng(algname, key); + if(filter) return filter; + + filter = lookup_encoder(algname); + if(filter) return filter; + + filter = lookup_s2k(algname, params); + if(filter) return filter; + + return 0; + } + diff --git a/checks/dolook2.cpp b/checks/dolook2.cpp deleted file mode 100644 index 51ee8fec1..000000000 --- a/checks/dolook2.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include <vector> -#include <string> -#include <cstdlib> - -#include <botan/botan.h> -#include <botan/lookup.h> -#include <botan/filters.h> - -#include <botan/hmac.h> -#include <botan/aes.h> -#include <botan/sha2_32.h> -#include <botan/sha2_64.h> - -#if defined(BOTAN_HAS_RANDPOOL) - #include <botan/randpool.h> -#endif - -#if defined(BOTAN_HAS_HMAC_RNG) - #include <botan/hmac_rng.h> -#endif - -#if defined(BOTAN_HAS_X931_RNG) - #include <botan/x931_rng.h> - #include <botan/des.h> -#endif - -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - #include <botan/auto_rng.h> -#endif - -#include "common.h" -using namespace Botan; - - -/* A weird little hack to fit S2K algorithms into the validation suite - You probably wouldn't ever want to actually use the S2K algorithms like - this, the raw S2K interface is more convenient for actually using them -*/ -class S2K_Filter : public Filter - { - public: - void write(const byte in[], u32bit len) - { passphrase += std::string(reinterpret_cast<const char*>(in), len); } - void end_msg() - { - s2k->change_salt(salt, salt.size()); - s2k->set_iterations(iterations); - SymmetricKey x = s2k->derive_key(outlen, passphrase); - send(x.bits_of()); - } - S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i) - { - s2k = algo; - outlen = o; - iterations = i; - salt = s.bits_of(); - - } - ~S2K_Filter() { delete s2k; } - private: - std::string passphrase; - S2K* s2k; - SecureVector<byte> salt; - u32bit outlen, iterations; - }; - -/* Not too useful generally; just dumps random bits for benchmarking */ -class RNG_Filter : public Filter - { - public: - void write(const byte[], u32bit); - - RNG_Filter(RandomNumberGenerator* r) : rng(r) {} - ~RNG_Filter() { delete rng; } - private: - RandomNumberGenerator* rng; - }; - -class KDF_Filter : public Filter - { - public: - void write(const byte in[], u32bit len) - { secret.append(in, len); } - void end_msg() - { - SymmetricKey x = kdf->derive_key(outlen, - secret, secret.size(), - salt, salt.size()); - send(x.bits_of(), x.length()); - } - KDF_Filter(KDF* algo, const SymmetricKey& s, u32bit o) - { - kdf = algo; - outlen = o; - salt = s.bits_of(); - } - ~KDF_Filter() { delete kdf; } - private: - SecureVector<byte> secret; - SecureVector<byte> salt; - KDF* kdf; - u32bit outlen; - }; - -Filter* lookup_s2k(const std::string& algname, - const std::vector<std::string>& params) - { - S2K* s2k = 0; - - try { - s2k = get_s2k(algname); - } - catch(...) { } - - if(s2k) - return new S2K_Filter(s2k, params[0], to_u32bit(params[1]), - to_u32bit(params[2])); - return 0; - } - -void RNG_Filter::write(const byte[], u32bit length) - { - if(length) - { - SecureVector<byte> out(length); - rng->randomize(out, out.size()); - send(out); - } - } - -Filter* lookup_rng(const std::string& algname, - const std::string& key) - { - RandomNumberGenerator* prng = 0; - -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - if(algname == "AutoSeeded") - prng = new AutoSeeded_RNG; -#endif - -#if defined(BOTAN_HAS_X931_RNG) - if(algname == "X9.31-RNG(TripleDES)") - prng = new ANSI_X931_RNG(new TripleDES, - new Fixed_Output_RNG(decode_hex(key))); - else if(algname == "X9.31-RNG(AES-128)") - prng = new ANSI_X931_RNG(new AES_128, - new Fixed_Output_RNG(decode_hex(key))); - else if(algname == "X9.31-RNG(AES-192)") - prng = new ANSI_X931_RNG(new AES_192, - new Fixed_Output_RNG(decode_hex(key))); - else if(algname == "X9.31-RNG(AES-256)") - prng = new ANSI_X931_RNG(new AES_256, - new Fixed_Output_RNG(decode_hex(key))); -#endif - -#if defined(BOTAN_HAS_RANDPOOL) - if(algname == "Randpool") - { - prng = new Randpool(new AES_256, new HMAC(new SHA_256)); - - prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), - key.length()); - } -#endif - -#if defined(BOTAN_HAS_X931_RNG) - // these are used for benchmarking: AES-256/SHA-256 matches library - // defaults, so benchmark reflects real-world performance (maybe) - if(algname == "X9.31-RNG") - { - RandomNumberGenerator* rng = -#if defined(BOTAN_HAS_HMAC_RNG) - new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); -#elif defined(BOTAN_HAS_RANDPOOL) - new Randpool(new AES_256, new HMAC(new SHA_256)); -#endif - - prng = new ANSI_X931_RNG(new AES_256, rng); - - } -#endif - -#if defined(BOTAN_HAS_HMAC_RNG) - if(algname == "HMAC_RNG") - { - prng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); - } -#endif - - if(prng) - { - prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), - key.length()); - return new RNG_Filter(prng); - } - - return 0; - } - -Filter* lookup_kdf(const std::string& algname, const std::string& salt, - const std::string& params) - { - KDF* kdf = 0; - try { - kdf = get_kdf(algname); - } - catch(...) { return 0; } - - if(kdf) - return new KDF_Filter(kdf, salt, to_u32bit(params)); - return 0; - } diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index 88a72afde..9a94d8474 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -53,9 +53,23 @@ using namespace Botan; #include <fstream> #include <string> #include <memory> +#include <set> namespace { +class Benchmark_Report + { + public: + void report(const std::string& name, Timer timer) + { + std::cout << name << " " << timer << std::endl; + data[name].insert(timer); + } + + private: + std::map<std::string, std::set<Timer> > data; + }; + void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec, Timer& enc_timer, Timer& dec_timer, RandomNumberGenerator& rng, @@ -603,7 +617,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/timer.cpp b/checks/timer.cpp index c42aaa4b2..8460257d4 100644 --- a/checks/timer.cpp +++ b/checks/timer.cpp @@ -1,4 +1,5 @@ #include "timer.h" +#include <botan/benchmark.h> #include <iomanip> Timer::Timer(const std::string& n, u32bit e_mul) : @@ -29,6 +30,12 @@ void Timer::stop() } } +u64bit Timer::get_clock() + { + Botan::Default_Benchmark_Timer timer; + return timer.clock(); + } + std::ostream& operator<<(std::ostream& out, Timer& timer) { //out << timer.value() << " "; diff --git a/checks/validate.cpp b/checks/validate.cpp index 8fb225137..ff26e855a 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -10,6 +10,8 @@ #include <botan/filters.h> #include <botan/exceptn.h> +#include <botan/selftest.h> +#include <botan/libstate.h> using namespace Botan; #include "validate.h" @@ -43,11 +45,10 @@ u32bit random_word(Botan::RandomNumberGenerator& rng, } -Botan::Filter* lookup(const std::string&, const std::vector<std::string>&, - const std::string& = "All"); +Botan::Filter* lookup(const std::string&, const std::vector<std::string>&); bool failed_test(const std::string&, std::vector<std::string>, bool, bool, - const std::string&, std::string&, + std::string&, Botan::RandomNumberGenerator& rng); std::vector<std::string> parse(const std::string&); @@ -150,7 +151,7 @@ u32bit do_validation_tests(const std::string& filename, { failed = failed_test(algorithm, substr, is_extension, should_pass, - section, last_missing, rng); + last_missing, rng); } catch(std::exception& e) { @@ -180,21 +181,42 @@ u32bit do_validation_tests(const std::string& filename, bool failed_test(const std::string& algo, std::vector<std::string> params, bool is_extension, bool exp_pass, - const std::string& section, std::string& last_missing, Botan::RandomNumberGenerator& rng) { -#if DEBUG - std::cout << "Testing: " << algo; - if(!exp_pass) - std::cout << " (expecting failure)"; - std::cout << std::endl; -#endif - #if !EXTRA_TESTS if(!exp_pass) return true; #endif + std::map<std::string, std::string> vars; + vars["input"] = params[0]; + vars["output"] = params[1]; + + if(params.size() > 2) + vars["key"] = params[2]; + + if(params.size() > 3) + vars["iv"] = params[3]; + + std::map<std::string, bool> results = + algorithm_kat(algo, vars, global_state().algorithm_factory()); + + if(results.size()) + { + for(std::map<std::string, bool>::const_iterator i = results.begin(); + i != results.end(); ++i) + { + if(i->second == false) + { + std::cout << algo << " test with provider " + << i->first << " failed\n"; + return true; + } + } + + return false; // OK + } + const std::string in = params[0]; const std::string expected = params[1]; @@ -210,7 +232,7 @@ bool failed_test(const std::string& algo, Botan::Pipe pipe; try { - Botan::Filter* test = lookup(algo, params, section); + Botan::Filter* test = lookup(algo, params); if(test == 0 && is_extension) return !exp_pass; if(test == 0) { diff --git a/checks/validate.dat b/checks/validate.dat index 675e1afb0..875177868 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] @@ -22932,12 +22945,85 @@ F922CA875B991A31:2763F255636A34C1:22EBE7A30E8855B3B453A6E926D4F187 B4ECC305C3DBD8E5:FBBEC8F5DBF4CEFD:1B5E23EBD915C1FEE59F57DD91AF7347 3DAADD7A9633E19B:4DE5C07EA1564A64:A6BFB85FA91B8CA4197C8B502A62F972 -# MARKER: Cipher Modes (Encryption) +# MARKER: Cipher Modes # Cipher mode format is plaintext:ciphertext:key:iv # 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:\ +B2288B968AE8B08648D1CE9606FD992D717EB02EB81A2E939D54ACA91087112D\ +0D809C5EE82F477EBA7B956DBB23463B0F0190D616F5294112FFB7884E8B37F9\ +41BA1B505386B7428B88338188F7E718A3348230BF5CFA552F88D22463D9703A\ +115351622E016BCA26918D17E13225F67EE4E3F2C46FE52ECBDA044C585717DC\ +563A8403FF5309D62370B1DCF5A11EDD2F7D73602B70CD2553E44C1D3F170126\ +155BBD9BE3A965B345E834718F651CEF6CC65E8C5C566E894817350F497816F1\ +EEFA51FC91FEBB6E9F8CB141CC0EB6AF3C6F8380CBD3C996167F2F0E90E71B75\ +6C87EB62A4975356B28DCBF6A64A0BD107206D48FE6DBE19D50314B90AC87B83\ +35706F9B26007071AD8105CFAA1C1E2FF7FEAE5CEC4D11477F24E6B200906870\ +3C0E29E2950F2AC2DACD63DEEB5C7EFA9FDB9F3B740563D5518287DC981FC9CB\ +46D4B5A5A86FEC08FE70D18297DCF51072DDBE038DA040EBB12C509F5940A212\ +DDEB59F02132BE4581FC23EABAA960D6341D9352E36DFD6E4EAF0F6F439BC8CE\ +73A9AB3164FF30350F2DC08E939A104D6DF0C2C28F8E2D44468A61278BB6B429\ +4DAE45AE0CAA032FC97CD4D8C57FB83BBA8AFCAE22070BC882D3A42B38A09E65\ +58A51ED82169DE7027CBE72452626CA3FF6BBF2FB2C574EC9D5656505B516880\ +47AEA89DBBB5C4EBE819C5BDFDAB16033D2FE7D01071373624D99845D90E32C1\ +708C609C4E75BE40D8DE77F8EA78C2CC98852792C22E971F29C2E125247FB43C\ +AD1FD857DE9B8016C5971FFF86AD399ED669FEF7481FD73B9A45B1CFFE9C556D\ +AE9A816916FB1F5822B2CEC8986F6E5B156775D0F6F432D57D351C62A24AFE63\ +AE812270F7416D05E153E5AB703DCD3FF320F6AD3D00647C23F08699E0EE9F5E\ +DDB3C717C2A6D3E58D38269DBA0243926D64CCD92B1101086DD3F0DDB73312A3\ +1D5F5EA0FD18AB84E242C96FFCC222F9FE12D5B15F5A3C365E9FF3248FB43B38\ +5A0F73507F49A08E68952BEE09DC7D35E7B29A44C8970624CB3A93DA4AE7E498\ +35AE41A5BE2EE591750FF9A7D431B1EE8A69099E689A06324AA0AE431ACAE762\ +FD3B90A8B269090A4CEEA076CF1EB7A580DEDE896BED63917384B1C5E18B7B57\ +A7EB6B127A7A32898989E32CFF9A46BF6A62268500E53AD8A5FBC95226266BD9\ +AAE1BA501274C49A7A7EC67D7577114B7707DAB9D066AF086C09E7DD4116CEA6\ +EE25DA9A65EF05A31ED0BDF56D525EC8968D1D01AF7165C5AEAC76BD367A575A:\ +00000000000000000000000000000000 + [DES/ECB/NoPadding] 059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE 4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF @@ -23569,6 +23655,13 @@ DC7E84BFDA79164B7ECD8486985D38604FEBDC6740D20B3AC88F6AD82A4FB08D\ 5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE:\ 2B7E151628AED2A6ABF7158809CF4F3C:F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF +# Test with 15 byte IV (last byte implicit zero) +AE2D8A571E03AC9C9EB76FAC45AF8E51\ +30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\ +9806F66B7970FDFF8617187BB9FFFDFF\ +5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE:\ +2B7E151628AED2A6ABF7158809CF4F3C:F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF + 6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E51\ 30C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710:\ 1ABC932417521CA24F2B0459FE7E6E0B090339EC0AA6FAEFD5CCC2C6F4CE8E94\ @@ -24214,6 +24307,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,1049 +24984,2357 @@ DBCFC865520E4DEFAD4000CE0EC528916A415C4661E1ED7095E5777BF375DC31CED5F966\ 11C63D070095FCD408DC7E7596C177C0A09961B2BDCB6E7C0F300C918E7E830B:\ 41EF5DF5CF14D6D2C14CC4CBC4EADAB7 -# MARKER: Cipher Modes (Decryption) - -# Cipher mode format is plaintext:ciphertext:key:iv - -[DES/ECB/NoPadding] -86A560F10EC6D85B:059B5E0851CF143A:0113B970FD34F2CE -3FA40E8A984D4815:4E6F772069732074:0123456789ABCDEF - -[DES/ECB/PKCS7] -17AE296967C5D076::AD37078F3EA426EF -A9E2BD3B74E7F3CE:E7:9CBEDD92FF2A5B73 -059CF1BEEADC62C2:896D:2FDB746F903CAD45 -784F42BF01754613:C1B1C1:64EA8FC0D24CA010 -9F4559AC8F287060:0888EC54:4C836F4563DF32BC -9553EAE17C9554C7:5B0E9EFF57:C6B1BAA1CE9585AC -3ECDE9A96CC20C64:3D0B96172D78:D75487A2708B6667 -05CE6E5D61EF4C58:90628E099303AE:3B7C17F8189C21EF -DC9D7EEDF77F3B4685EF88B5E3736DF0:3216ACECC41D0D6B:D53C39F84A7E53A4 -EAFA4A1BEB450770265C5AF8A87B807D:8C04066386282D98D5:4637A64E19D8C59A -91A2C846731747F490596CC2C1354E2C:D2802A5A871F246AB192:0971FEDA66F7DD2E -8763EEF91B589B6706EE96108DDB9A70:D3E87AF21F0313835ADAC3:8E8F17C42B91EADB -C75CC89A8B528B1CFA9725A4F6F22C9F:D6FBF31C50BEF03DB36D9CFA:A87F5FF0B3545400 -3888F955A7079C88ADDFEE8C5DDDDE85:40C86D519650F7506BAE823B89:6DA82D72B5948390 -FACCCE40C05A410B329340EEE8E63E89:\ -0780C2ABA3516BDE2A2F8970EB75:040128669CE30F4C -7AFE6045F807102D354B17B45F3D9D70:\ -BEAFD7CBD536B9800B10F9CEE81E72:A25AA7C651B67CB2 -2985CE350364A85067F32C4E5D340F1658E77714063EA91C:\ -3D8DDC8C215EC27AE07C428D093DBEBB:E4E5E82C29060303 -C78110FF4EBD0FCC3EA2A8F1B3CFECDAC527FF08EE874167:\ -BD6FC0629E56D7E151AD3BC303B02852E4:587033C361C2413E -02F8DC588D26A55A5B8E441FC66804CAA198A38CF5837A96:\ -8AA4B5C93DB2727D4997927B4570DFDF630E:9A65A821B5FB59D9 -FDBFEBDE42AD8228D33B0032ED35B4AB687BB44CDDFBFC78:\ -13B6ED27218594D16AB5A8475BADA80C03E36E:ADFA49E8BD20F49A -43391357D31B758921A07ACABEDA50025421B9A15CFFD863:\ -4FAFFCA861CDD5B7393C2F1171E3EAFCFF1BBF09:7C4C08429BBC99D4 -1BEF25251A46159EDC6E7410E9A3804E4DE32A202E2D3FFA:\ -4F246C4C3F679CAE3D659820ADF948B04DA101AAC7:C4D15330927DB0D5 -BAB47B7AFAFD30234BC4E69F1A602788B294438296F6E046:\ -C00AFB680484638EE4BC8999CAAA7EDBF32ADD6A32CF:DBDEDFA4B3BCB30B -006EE0B1E90468292B72A70426DCD3975A6A4F21D6F6DC8A:\ -94CFEC7A15A35441AC72222DC4BE7508CE12B1D9690E86:95C9471D839AC3A0 -7DA18BB325DABC8F5DDFBAF9B41F4389C0FF9E37A86A1E318C9065FC7F3D654B:\ -95F6A941BBA9BA711BF1962D668996A315157A49EE32993B:F22460847CD66211 - -[DES/ECB/OneAndZeros] -D573EBC3919CB0FB::9EAEF4F67688739C -96205FA42306698E:56:FCC8C062DAAF3A6E -C2A09626D3200B09:7106:F4FA38ACB1D2A9C9 -64850779AD424E5B:9B5D19:FFAE7E198369326C -5A4D009F2ACFD643:30A671C3:585B8E1A64E346FA -BD29AF6B945A8413:371415B9FD:4B6C26F53E7317AE -6904EF148ECF10B4:1F5E2F5D845C:361DF31C6F8E772A -4A749E5874DC2FDE:FFCB40A7CDB5B6:050025D50D9773E9 -72EEC4B5CCB537C1AA223E5DF3368139:610F58A0A16D1303:D4F1D443093CF941 -25259E1C4C1E65966D933ED350668BC3:171A5D4E209F133F3B:CA2BD0CF16C9D7BD -70C87505241FAA9BE93633B16880856D:927D2B314B4CCD1F3D04:C64374B9C7E2A06E -393C836014C3A65EC36E6165CE192CE4:2CCC4DA982CF67BE929C4A:E30F4BDF1B96967E -858A4172FAFD4614B5263F418EB9EC56:4E92F895CAEA28B7208236F9:308DE63A2E3A5BCE -2716D7195AC4D979C3F81D3D08897E8E:E306358941C2BAFE286043A113:33482C296BD8D44F -5217205AC00B31FE8D7CDB916AD49773:\ -5ABDB2059249D0672AC52085985E:C893C0B250AAD5F9 -1651D5785652365C03541F62BDB343B8:\ -D9E343F4A600D4C5467FBBB923BFDF:9490B296D0EA218D -90C4F548C806B6B86EC2BAF6A96CEC5D9748FCA16CA51F44:\ -D3DCA72E82C0572ECC7C0DF2BE150C00:F5A1291B1A39F5E9 -39EBA35BF86A2926B0A489599B4BF94C31A9F7FEC351ECE2:\ -5E3786F3E7B3D91AFEE1295C314AFBAFC5:83B78C6CEB56CE78 -B32E06E80854E4B815E12F61A2431B7E9F378ED825168C33:\ -6DAFF95A4C3E781594AC22BE9E9E3067CBC5:1B5E0FD12573752C -BB8FE34DE658F8E9D7CBFCA9EF0D5AC7CC48949FD419663A:\ -8340DED8A3C5DFB4C59857E5C7B066D5FFEA84:D78448EA1E73DFF9 -A6CC24FE20B8D417592A12E4912A131BCCF69B71EE25B420:\ -5EFAB4221460C884D8E84FEF593E7AD2FC065AB5:A960C2DF2037A814 -4373F2160343E9E626A13A3D28B5D9A1A6E19455374A7070:\ -BB2EEC90C104A60DA2CF1C31A1D06B84C58C55B396:001247D9B6B26506 -F92FA72F2295337D949F8F2C34A0CCA63D0A2057CB2E6F5B:\ -A3F7B5142BE18B4F54F828F42D1BC5A3643016974399:E6FF6AD89409898A -06C29E86F4CE77256D64E320F6A6A9CA8A72336469DD1EBC:\ -249986A41700E34D49F01D21CC84059D824E9DA320FB6C:761B7C6F0F783305 -75190AC0CF194DD8620D6E6A664E5F7FFFCB615AAFBB098EF54F8430616767B6:\ -3234B4AF6F4B7CC0527C4D23DC7F22BDBE84E7BE010C2F39:F4399D05D289A404 - -[DES/CBC/NoPadding] -E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F6:\ -4E6F77206973207468652074696D6520666F7220616C6C20:\ -0123456789ABCDEF:1234567890ABCDEF - -[DES/CBC/PKCS7] -07E8E4E137A70F64::FE4BA85E69877F56:C5C7186B1F9CD61C -D452289D1ECBFB88:DD:23FB4CBFC76F9906:550DF2EE0D0ECC39 -5270ADDA7C33A133:0AC3:4DC779C79E31D084:B6B763B034D4921A -215580AAAA09884F:5CA7BE:07AD83CA822CBB58:2FCDEC1E5CCC7DCA -1E89C0730B3ED0BC:7AD95A87:4C66AC5320597311:378EF56C445206CF -4D0B351457FB1D19:F1ED735A21:ACDA801121815F40:4254636AAF235A60 -4FBCCA8DBCE392AF:C284BFF3333A:66105A77286C96F9:4F4BAC49BFEE1523 -101115733330ECE5:3E918010C3A311:FA43D72CDD6A4F04:D8773D690E7EF671 -8996ADE0774169D11A1EF78E157AB3C9:3A913A52D35F6D41:\ -82BD7722A5704C2C:7D59C67162592989 -A0B1C44602858AFC9DF4FF3703561CF6:C4E77206DE7FBEC001:\ -C4FB35FB4CECCA1B:91C5204B300E9C8E -5EEC6084E8EA4CBD226B1CE9D03760D7:C2FFAB037354BBF6681A:\ -6462FEF31CD53A14:15F7C886C55B8C80 -635F4DA9940E6BFF3475718EC80A6032:B38993F0421A9482256C3E:\ -B1F09583E9F4332E:6B3A296CE234FFE4 -6C427B05365CE2C1CD7272F4580FF4E7:FC39AFC5C58A746797C64540:\ -C2509FECD82996B6:FCB3F5AC6122AAE6 -C48B1AED56789C2ABF1DC0A3F0F09D95:006F3067DA4F4EF4294925551F:\ -83FC0D025C2B27D4:8A9424DB9F60DB23 -ED198040B7F952B3B2C7B550B8D3E207:8953C0470CC17BEFDCFD7A178941:\ -B29FD310B15FF558:0D832323132E79B4 -F562D640B39DA7BBC5F7FBD0B84EC880:673D81110782DEB537CE33A0DD8F96:\ -E5F2856E63C54113:EEF1601F3C40CD8D -492862C0FA48CDBDE714A0B8881BC1CE6F9F17E9A2754D65:\ -8F4169CC8771200D0BF3D8F7140AA811:\ -5DE9685DEAE62242:3835A7308345E312 -F5B8D08D269EC0F196BA8BA6BB98273F8D90325CEC83424F:\ -8DC4099DC33743F0E6B903CBE8FFCB7C68:\ -1A99B0DAF28CC879:2AFF0DB963454727 -C2DC32BDDA790DADF329874B09727A14BE6F01E097AE5B1A:\ -6EE8C6C2C73E58C82D58105B005149DEAEC7:\ -5ED0CB977CA524B1:4F45E91DE65705AD -920184D9311F88F5D0725F4F40B066DB6FFD1CE2AA86F933:\ -968F75526E091CAC8BD85DD75AD15D49E38ED9:\ -6C9E8BCC4C9F7B91:21728BE0081A555B -A6744F04F97363A5EB120F09DFF42275092E587B14D12492:\ -CD4CBDDA85C9B9E7DE97209472BD2BCF9182150C:\ -9908A488E9ABB414:958C9C62D9593C5E -60B161ACFDEAB66C476EA55D13116F865687F06CFFD13CB3:\ -F58720F8B80AA229BD7642AD9807C647839D853033:\ -61F2CCFC031ECEFF:9F94F426B4ECDEBE -8751AA8954A97684A06B2BFBB85133B33D3DFCE1B8562156:\ -A95527CFC36EFDE34B771A0370ADB1E49879AC424D66:\ -F8A2DB331D17C3BE:AF6D13D63CD74439 -FC16DDB93CAB78299B5A18D9417DFC5A84565BE49057C394:\ -604570CF9BCCCC86FF411D0774AC6559F8D293BEBAB80D:\ -B8D057BA9652F60E:B23B7F81D64B4E5D -C3BF0218E9F75F284871BBD4D4CC6664D964EA0571FC40B1CA54BDB04105DD65:\ -4149D929BC228216A0D58E880112BE987BC1BFEA70D7D9FE:\ -283320F2BDBCECFF:06C528C2E7AAD887 - -E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF277:\ -4E6F77206973207468652074696D6520666F7220616C6C20:\ -0123456789ABCDEF:1234567890ABCDEF - -[RC5(8)/CBC/PKCS7] -7875DBF6738C64788F34C3C681C99695:FFFFFFFFFFFFFFFF:0102030405:0000000000000000 -7875DBF6738C64787CB3F1DF34F948117FD1A023A5BBA217:\ -FFFFFFFFFFFFFFFF7875DBF6738C647811223344556677:0102030405:0000000000000000 - -[DES/CBC/OneAndZeros] -79FCDEE6F5A94E74::0741219814F4369E:DEFD8C15FEB10458 -54EC08B8ADBBCA8F:61:113F04B28F2A9B7E:46A8D61A1D40091E -7F5C2A6A9F539AD3:6162:7A1771070C736156:5DB9B23CCE795B60 -F0103B237AC98CE5:616263:C4FCD43F56E0AE9B:23A3C25145BE0D20 -65997360ABB15119:61626364:C4FCD43F56E0AE9B:23A3C25145BE0D20 -34D30333EFB7979B:6162636465:F0C27E2EA299D6B9:933CB62A4B934A86 -875E07E80AD49DA0:616263646566:32B6417E7DC574F4:7B42506B38E4A6E1 -994B8B68EE1B0599:61626364656667:3F269D9FF30313AD:DC044A49A694D3B1 - -C224E73B1564AD1FC49353481E6F5E1D:FE21E07064BE5336:\ -80A21AB24ED705D6:ED03EB0F3FB37D02 -55E901FB4BADDBDF1EAE173AFC8D7099:BBAC475C9BF8287A77:\ -CDCC24E1F5D9947C:EAF397A30C64F5FF -6105DF0EE9CF1EBDE42935D364D6C9FB:8C5350033553101EC583:\ -94DB8915D14857F3:91499DE2964505D3 -690EDC0411344EC2B0C7B41A31D2F1BA:F3DD004162E851F63D2340:\ -E32708EEC7FF69DA:5782AB9B02BBE4B6 -CC613B80C91901B3216AD10F6596D8F8:4C609BE7D7F14EA806AAFB56:\ -4F6A0EEDF83718D3:FCE76482531A27B5 -63AF78D1B2A15AECDA6897AD6007E5AE:CA17CCA6AF2B27A30B5F92A2B0:\ -C26991460E22605C:126CBBC4A9FC3EA5 -A096512FB2DA7D0A75A1DA41F234A83E:C2DFEE0749C5A21378D4506AB8A3:\ -07D0D1AF072F0737:B66510CA43FF801E -E641C41182D543E18932FC306FD30726:5A9450CF73A49F570860727C070012:\ -533571A680807F5E:D0FB32F8A2CB7D8E -9C1AD6A9705F9A72069BB0E4D51A968C2399686815F8DCDE:\ -04184EF5DD2105CC02AFA58B68C2C7F4:ED8250E6E97FA6E4:5CE0CB36A781C6AB - -EC41D8E3AA50FC221295274F65A76330:\ -6162636465666768:9F853348B078828A:1DA8B83A9ECB0F6D - -69E0288D17900DA45557053EE79CA771E90CCB8D28198E0D:\ -435255534820414C4C2048554D414E5A:\ -E3BB33E82BDB2B84:593A08135216F478 - -14D752E45A8D28EAB2A5C8E0A12E8A88E804451282F62CA5:\ -7777772E6D656761746F6B796F2E636F6D:\ -458FD140271920A6:605C41F0790BE4EA - -[DES/CBC/CTS] -1F807F8FB9678124B9:9E1CA14BE6538A35DB:88B23AFD0683D337:BAC170D943D262CE -C6FBE4158F2939D81685:673E242016F6BBA293C0:FFFFCD5B8461A7DB:6D688D63D006AFCB -F09F7DEA21F678D8FDF997:\ -15FC19F91682B6DD84E60E:4520E59F0868DA60:D572977CA711487C -80D4E9906F5E093CAB19C835:\ -07F07F2E6E08B791641A95F9:E6A1584C2D9B0F7B:CFDCEFA5DC5CEC3F -1D7DFB8D1670FFA2FDD99872E2:\ -CC5B006B635A022707AE5674A2:3F2B64EC09DB383A:CC26B1221547BBF3 -DEF7C893EFA8282FC430D92DEC8A:\ -25D30B3604955F5D9AB140C0CA08:41899DF2C47BB49D:E92788E786D65178 -4B0DA5D1E34EBC1AFD0EE115F6D6EB:\ -3736F5354719478759C0AE03FBA044:E15683D9B9731171:6055901E02CC51AA -13EBA3C09DA9A92CE12FB67D8D0EDED1:\ -121BE08F10A108CF04F6BD59F8A80EA2:EB1A14148700BE54:93AE09E97D6068AC -A3F29A3DE6B3D52054CDC85FEAEAD5440E:\ -B394FBF91C772ECF3964975819DDE9380C:166B1D73EC15EE53:477A1026883D68F8 -DF6B5B1591C712562A19631E8DAD95153F49:\ -E2416356E94211935EC4448BE0AB43EE1A80:2F01F85201D1B010:5066B27BF6719D41 -FB7FDF98254DA02C2FF2A7801EEC8CD4B5DE03:\ -50FD46F08A0EBC980F24C9484799EBC2028F75:2CA90BF9C26CCEB4:50446BBB5961F03C -DAF13C5B1DBB958869C0633E8F7EB75646A17647:\ -CF81978920DB7182CF7CA7B5D1177DA83C372C4A:29B6B35BBD8575B3:76EC8D7FA07B8BE5 -87F9684E940E9C410327370A9F10270081B0A5B431:\ -FFE5FC92FBBA432A381F0CA62691AFAD668A0AC192:54ACB83F531EE8EA:9CC628CC5BDEE576 -E2BBA60098114B85838CCA4F1FC8D22A3D8234E0D796:\ -F84EE66897F4D44F882304C3C7D5F630BFD47250B6BD:C562A007017EFC2E:9E4C18CAC2C60138 - -2DC5DBB9A4F55CEB1A65871417FB293A9726642DD02171:\ -3B4EB0E3405E17EDD17856D29AC97E7B6E3BC196802A24:\ -4A403657C2102B99:90474AFC765346AC - -B902D393A62F51E99CBC97B1310830767557835CC56BF88F:\ -506C86A1D0E325684DD23BE8445CDB08D734D6FAA48BC1F8:\ -CAC16F52CA80B183:CFF070594D1A8020 - -BE082E12FA28CEE1F24328D50FEF71C055D61A6B71466EE56C:\ -B03B09966AC8261CBD17E6CE218B4A826B3D0D36C735BE1CB6:\ -2FDF8948B7AD54C3:8CBDBEF17F1B1328 - -C9C4702752294E5C3410071A0BF19549AF90213619754EADA1F7:\ -4D790FAB1374E5387CFC5AE9E7FBE0ABD57F634024BB32FA6D95:\ -6A277A4D5B27FECA:6007E397C5E1B6B2 - -C91A1979FA1A4F93FB8FDA30BD82C26EDD397D91146C044D3C9AB5:\ -01FADB9D549F559E4BD4AABEA073166D76ACB68B3BC7C38E758CE2:\ -E554075663480335:287B947D8D85E403 - -ECAE28210D616F758CA9111276A10D2151E3F7D0BC567D88944FD697:\ -4DF4CF96C82CAFCCF4791A26DB3A55E8FFF1F374020B1495AFAC8B10:\ -81CCB226258A2BD9:48CEEAED7E7D2B60 - -DA5A434A5416AEDE9AD557F48183C32406EA78FF5B3B37D5069A8077F8:\ -EB80E96A60CBE0E7E430BCC748F4CBCD61382FEA8787AD11DD598A202F:\ -BAF7BA1C4F38A3FC:13D4AED7365948F1 - -243B2A015703ECD61FE8DCCC3B216389AE437C0582F5B96493BBEC9B4C68:\ -8FB383275E6F93391E97B13EFC3F7C99F731CB1B346EB15BB5F8DA6248A2:\ -24EC41340744EE04:811219783983A9A0 - -7CF27928B68E2A4CF007F5C740EF3D42E3C86AD0A768C50F65A92F7EF76CC3:\ -A3165F6001A3C69BDACEF31D924F4CE8AC9CC6CD10BE9948742A2E98DBFDF0:\ -A9A60A3BE162FA91:771A271B54C3DBDF - -0190C2294922A17D6E40B2595C9552F0D460F1552315D964818F01CFC7836E74:\ -E6DD056E42D117095F389321E259A004D467096DA28EEA534DC6568C3485B9D5:\ -47B469F51A41EC35:623A5F40A498554B - -BAEFF9B09693512CAE7CDEE14628C39898360AE20BAE66C845D920FE16F6D626DF:\ -4D0E59994E070D66F913698947E4AAE1F3044928F29D4ED59CAD18D24E134C52F8:\ -E8C7568DD459A5D9:F82C3042C634B503 - -B60D0279220B5AC636A861AEE3867B21533A579ABADD3EC5CCB7DD84B23AF3794CC6:\ -4786F439927802927B1AFB3B0DB3C059CA36E4E9D8851C304ABF12438A5F1D7C15E8:\ -5F4379FC61646FCB:8FFD75FA48D32230 - -245DD4A56151DCDBD0000DF64239D4E64CBC9E82878E3465BBEB86F8DB4782565DC96F:\ -12B6CCB90894783FEC5A375C1744BC7E276DF3D21433EC842373FDDEAAF4D2FCB4229C:\ -1B9F7251AF742AF2:61E984D8B88552DC - -3B7598C46993B7046BADB4240143B112CAD1955913073B61E1F77871300A3A4933CE98CC:\ -B84AA9F532EB1DAEEA5332BCAF2402E4CAC762CEB614A686A7A5483AC968FFE6FA84282E:\ -CDE1C86F35672CE4:4B1A4FD4B170196C - -5EF4F1E99D2B142769C82590356C5C69C0B3524FC5F849A583464F6448420A7E1FC3563BE0:\ -16064D069A02CF2F8E05953D3B94764568A1C9A1B12AB56CF1032BEE90DA83A807ED5B9670:\ -D427CDE3D72512B0:DC0C33ED870E2BFD - -BB8ACFD2BDCD37D952FCFB3C4E668AA5A4EAD2273BD6C84DFC0E8E55AF2DC54D7E3C908FADF7:\ -2E682E802242ACD731E439A7392A5F8701256FD23BA03A65A723671920228B34EC6484E53AB4:\ -57EEEBF7FD0D4E18:B88F867E5276A8CF - -[DES/CFB(64)] -F3096249C7F46E51A69E839B1A92F78403467133898EA622:\ -4E6F77206973207468652074696D6520666F7220616C6C20:\ -0123456789ABCDEF:1234567890ABCDEF - -F3096249C7F46E51A69E839B1A92F78403467133898EA622:\ -4E6F77206973207468652074696D6520666F7220616C6C20:\ -0123456789ABCDEF:1234567890ABCDEF - -0CB8929A854E61AB3BEB72CE0F13BA328BA73A:\ -D14FD67A9B4D7B0F65B7CA3DA91741603DA446:\ -7132D895529A7AFF:FA1FE8F921706C75 - -# Random tests, 1...17 byte inputs -8C:14:FC32B875389C53C0:6CAD29F658A72118 -4045:20A8:89D26DA778B3BA96:C6727E943ECFD50D -3C17ED:E13C5B:A9F4D6E479BDE314:271C258E90098CC9 -4B465AAD:DDFB818A:C0DF30CA0DC7B5A7:0F141E7F0EDD71DB -EA6E62D9AA:F70A23F77F:EB26600BD965DE91:6F700666CF4EDEAE -C486B45156B6:73B635137A36:C56CDC1349657886:5883CBD2A332FD55 -3030B2F0CF44EC:2160B2C75B616F:0DDBF5FF8489B870:F9E9C856200036D3 -C6D70FF570F90870:260C393389E6489A:4E96BA675101F1EE:4DFCB5C3570E2235 -966F556D1AB16D9A84:86083459660733A6EC:16ABBC1F03F13DCC:571EF2769E6DBDFE -42CD5A8DA77110EB8E56:300AB25A182F798D2195:DB2807197F31E79C:465C5C1BE8DC2699 -1A6829A79F40DBEA451043:2DFD811615ED4490B9AA6C:97D3995360F10777:B4D324EC37BC140B -D4736432091A2DBA9E7624D5:6BC6540B34674448AF311283:\ -6C7E65D7EECBDC07:2E41B63F4381C5AD -ACDDA761DDE4D7D23065726194:E7FE3DDC6257543EB319DD565E:\ -B55CB5A2BFED0E0C:C290747BAE6C2651 -E9CD9B31E903C3219D3D83D3B01F:1A17ADEB075B2A94777C8EF0ED11:\ -36982D604982EB26:B4AD47CB63991A37 -5501CAF4CB8843D460CE4D64AC9F3B:168583B6B5A1B5E8246EA11E1D5B25:\ -BD51A1B281929DC7:C5AAD3504E6C4BBD -D4FE93AD0BA52E4919308E1273714C52:CF0C5D133700651565A8C1885C1576B2:\ -A8C2FAA4B9EE7986:9B733E3380066255 -E4D2F1241759BDC21164DD17CEF53043E7:DB72BF34A34159D488F9C6537D062C8E56:\ -B90CAF95123094D8:48E6D697471B2639 - -[DES/CFB(32)] -13799E52F0BF6B0E:BF28A5B2F3FC788F:44FD92D1AF17DA22:5EF2AB4DE2C32258 - -BA696D0FEFF0882ABEF2E0BCC543CBE2:A6D36D854511809856A9911919FCF070:\ -5046A6A7584E015A:D006FDD64A63FFF5 -6A837A170812A9E6E1A5DC69AA6FBCE2:19359DAB792F0D020115A7722C171532:\ -B992C4C6A2320278:5AEF500DDD6608E5 -77672D81E388902A764B427DAC586F20:B4EABA09CC71CB3CFD191F20065A1B70:\ -E6862A4F40A85BE4:E743B2DD825BF2C0 -EF7DA9BCA94489CE200530EAFE1CD7E7:244273B4BD388B9099669BBEFDC4454A:\ -C4438F020753FE17:36AF1E8E06E278FB -9B51C216FBAD699636400C962F2E3405:3B9834AB792F727E788C7D32625455D3:\ -465537A2E2167EEB:CCFDB7E38ABF99D9 -19D49D5A54C8FD15EF317AFD5A87EBDE:302C49BF921E0516261F00B2FA2E96A6:\ -F15BD42AEA7F38FD:5E10F9CAF0730C4E - -[DES/CFB(16)] -D6522C5DEF57233BD3A6A30F457A079A:769DE609244B94A8B4E4727736DEA7BA:\ -E1D28FFDD5036622:7A3E915CE8A03836 - -E8E4A04E0F07E2D9:BD4E5489C5CC01C5:BFCA0E11D1ECFBA7:E115ACDCE0EADA59 -7DDE9ACFB699E9B4:CD42413995D601FE:EDFE86AC2EF8ADFE:4ABE7D04F174CA97 -5F803D644DE8B9E5:5D4B3F430AB38F6E:B94861B7AAB541D8:9EE77D9E68A0968A -3421750B8D2F984B:2230CF77A827A379:DCA93094B06CB02B:B7D1CF1634AC7D72 -4FBEFCBE20691E11:AA9DCA8BD9C31D51:6F4C469A7710EA31:D091690C4D0203A1 - -[DES/CFB(8)] -205EFAA6251E7659:C5A1343F4AC4DD7B:C42B0F47482DABA0:48848E073CF89946 -7B0CEB1D343B181B:BABB3F2ECEE17044:01E4B49A4C327C83:7837CB9035139E36 -FC48CB21644AA6A6:35BD7CBB4F42FE66:DF6B71F274CEAE61:8365BDF506BD2382 -7423BC2D230FF167:75648C39AF4DE0DC:2E1BAA1165A460A4:35E0A0149D95735E -8E511E034A21F8D4:6FFC4455799C1A52:FB029C10575CC9EF:DCC44B7A2C4912E0 -6AF4AA1647F5D301:BCFB89E0F3FEF946:468B7763A174FB3F:99057856B861F898 -8BCF14590ECECAB3:8A8907B5BAA3C332:60E50468766A6688:ADC6C30CDD00F54E -FB5984B0442353C5:59A6F97571EFBAAD:23A9AEAF310E7134:809E47BF2565701F -52ED7FC58FCD4DCF:B9B761F8C8AFD67C:E9480E1E6AFBA1D5:23D1BA6B06632D52 -7DFEED75F6A1306E:DB7A16136E5B71B7:C82593A34F75DF42:B6D33655396C925A - -[DES/OFB] -4E6F77206973207468652074696D6520666F7220616C6C20:\ -F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3:\ -0123456789ABCDEF:1234567890ABCDEF - -B25330D1CAB11FDDFF278192AA2C935A9C7745733E6DA8:\ -39B9BF284D6DA6E639B8040B8DA01E469DBA4C6E50B1AB:\ -F871822C7FD1D6A3:B311792C8BC02EE8 - -73AD356623A1D6E0717E838B9344B4FFF21BDA:\ -0C06E63E9E81D9976E16D2009255F917797D51:\ -5860F4A413DE6C68:527A1E050A9D71F0 - -08A6091FA2987FDC682A8199A6D6BD1F:640B5033DCF26873FA8A34DB644F2BF2:\ -3307042DC775035E:99DE32FF0351509B - -[DES/CTR-BE] -4E6F77206973207468652074696D6520666F7220616C6C20:\ -F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75:\ -0123456789ABCDEF:1234567890ABCDEF - -11919B328564DA68D9F4216AE1B4FA7C46AFC7AD5BB867DF1834D77A3023ECAB940725AB:\ -F40235A0B8B2EC0B53F3C0D8799497463638AD0CC3E07F0E8B8B0DC7605AE6AEAFBA2A88:\ -A67ABE525A0E5AB2:727BECDE9FCEA20A -168A502D21D71F3BEB702BBF02D3F6D04B72EFF2F19EF01D217CC7AA739A67466AF3B14E:\ -3A73770D157C23EF8913D874CD92DD36C465679B2BC691DAA0DC6CD4591C4CA44D5D69D8:\ -CDB366CCD621D62B:1ACAAC3F760C674B -24889A268E11AEF80852C4FC4893DBEBDF4CB06115FD533650CA39A639C659F47C3D5556:\ -782B24067A2C5D61BF6ED2E980F6BB16A0A6E0B5639B4208AE273C0BDC0311D65464F217:\ -EF510AA740BE98CB:74E74E01E5C72084 -3078866926F75D18239A3DA92EC9EB88D18393440B47D46A49D003F2C3B5D51C1CFE3FF4:\ -DE4D9632BE88235D717B36DE4C67B81CF3331E8925726CAD1BCC05126B87A6CD5D5DE3B6:\ -E8CBB756DE4FDEB0:AEE751205CABA9BE -4602C97A25AFB1746DE8BC1A65AE0B635ADDAB9547A99421AD86AFB087997ABC1458F0CC:\ -754BD27902EE4248BEEE65D2BB035C9139F98735C85603BA9565EDAADE37A7FE29833DD9:\ -B050B286E47C6E6A:701F72AE37D31F2B -E344E0C2E45990C451C75BF74406821B99D4EA5F56F67BB2F9B0EA52FF5D1BB25D82A181:\ -1A23AD101A776F902B8DB40E273A1F5EAE8AA1E43CBA52546F2EC50EF32960BDD05101D3:\ -445A14B76AFEFBC0:EE2DD8860B75788A -2C3A117378B8DB1287CE8FE084EAA08EFCEB253DD4A92509EAD154E6AE483E25D2B790B5:\ -75235CB3E2BF7DD3ED893DA93AE25D7A34D43521DB620E2BC9072159357010E6D81E5884:\ -4B1B62B9D6B8F54F:036CC5145BCE2A01 -FBC7E48930ADF4A36DE18CABDE25ACDAC8F9AB727E3AA69FE8EC6F965C6E14EBE9AE437D:\ -B271913A8A58ADDF3C89132A15DF1263B63018CC8EE6763E6FCFB4DD5D4AA8EC4B3E2D78:\ -2E0F06AE7B1C30D7:05E144D6DB9E7939 -940C3FE78C56A0F922FBEDE7ADE31914C993BB84F5BC1557E5F8004CB75D7D339801FBBF:\ -9615A71536135E50946A8517E72A980CBB2378A3286F08E76E85E5FB62140C9B3720C7C4:\ -E6E85EABE538195C:B86615CDA5C9E9A2 -256ABA748AE0005A5F99F1C96F8A197E3867B8455A4D6BFD6795BBDB89062B222E6B0DD7:\ -2A6B043F07ACD99141C7AC616B7F89AB7E52174A41AFC1FD0C56BC77B9C2EC9CEC87A0A6:\ -9985CE7E0D79CFEF:25D1D57C3A6936F9 -44AC3E1333DE5CD00475317CBAD26AB4A812180DAA7405556C41335572F5A236C37CD36F:\ -155E5B86FC06AD433DAEFA05C329BC1407966220BA91EAC2FD32B35C5AD973D94A0B8792:\ -47550AB0F346ECB0:1C42F4559385E11B -9DEDC376CFD97AE823AB2E0CB0072DF26DAADC4FD9316C7E8F4F796026DA9ECB8ED69DCD:\ -EDE3E69EE5B55AC758EB39E70E6533CC4D89C148F6AD68293E743CD82B9638F020EE589D:\ -098EFEE0D594C332:88D9C46E992B27AE - -[AES/EAX] -B39AB9280E8E75FFB9A6C0423D94237757:A1:\ -32942F082B82885F3965397EC13315D8:79E2ABF57EAB5DCBB887FC38069FDA38 - -F28FF0575837BBF9B18E1AF21F086271224BDC:DFA72B:\ -16EBB23CE362FE4F9D75D7FD330C57AE:13A112FDD1A803DADD153FCFF5E6FA0B - -79B15D05BD1198BCAFDC4E5479C94479EED48273:8EDCC43E:\ -5D83726C0764B9DE12E97C81D925BD12:E2614B57C71FC5DDE11AB56FF67AAD53 - -6CF9258B79066C6D1D3CEF7DFDC07F1CD3A2C456:2CCE2B48:\ -898EEA34047E0896A49BD8EC9E5FEF10:86B46B759E771F7DD2F5D6FEC401474D - -2B098DF40219F5378FE910750AA62597BCE7F2BF91ADF6AB8933C113F81E9488:\ -C202A2C43538DFBED961D4C6B9628E3D:D41C09CE65EB3924456360D76B78C42D:\ -7A67F1AF9FD16E7832423FEBA5CD2879 - -3592BF54500CAEA6CBB6AAAB7CB3BFBE::\ -CA0F81BA5479F3B8AC847B7EF116C2A1:29D2ECC2C99C3676E7B9F85AB3B1E57D - -4DA9BE08E753EA123DEAB8DFFBA315DB50:B9:\ -D71D44511C92B390AC9C7961506D9E5B:032E8F2C3E7E0B152DC087E20FB59CE6 - -178CFF2FAA32FF902EC92AEB5B30834B5758:0ADA:\ -39F797C50D5BC13FE895367BF2ABB56C:58399D9AA144C8236655F51D81FFF7BA - -37ECF2F5E41D4DFDDA3DA85F1D82A3767E8360:3CD5B1:\ -DEC57BD1A4D6B9C0160E53492DEC88C5:3D60B53B4A64D1F9B6802AF9BD00AB9B - -3165D9ADB4E3CEC0831B85AF88C5787C0D145A92:09FEC8F9:\ -7A09C4F9265809EDF4BB32E3270D6F46:EEF79DD485F69FA5D0457DD94345D2BD - -05B76D5CBE49DE233B6F62E4D87763FDD0A210A84B:F3C0EAE690:\ -9FBD4E3CC8B0B54454788C5B68AAC81C:2F0269EAF6708D3B1B332EDB1E146BBD - -FF9CAF05A8107C410BFCDD14E3852C5A76F8EB5C116B:1F31923D5518:\ -85ABF08534075B6EE35AD7C550794BEB:AC962D0FE55AA2972BC2C8BDFF1ED584 - -81655A74F4F64E21B004F3D04D56512A7D1EDCB9B20200:C7C8F67C72E962:\ -170247F224B15FE3D501DFDB21EEA1AA:46FB86732B98C18460897ADCFB643E12 - -D81940ACDFB353AF804BB411C6950BD8FF9E15067B406830:06C456B3B74175FB:\ -CDC09E48511B3E38B75D14EA069BC885:CBF80EE76101BA67C5111A7C528F781F - -DE25F7B65F16113841D5AE12F80A1744A5F81B09EE5D29240C:0B2FC9C8FA81E7198E:\ -165372615FB7963B7A6E59364ADAE29D:401A0B4312344F41FD173B7FFF540D15 - -BB873E2B7A879E53F513F1834C54853FC2037D9893F65824CCB9:DA2057C6401125A5808F:\ -2F32841E15A6A883EC5CE8032E563BB0:B33743A1061DC15DE3026E09A7EF98D7 - -304864E3B8DA2359BAF5ED60C76DB298E2C12E94D18FC615F934BC:20DA4B54F8EDC93EE5DF91:\ -AD94D86D3D05ACCE0FED495B6FF5F23D:4DE497550471A059698E22A773013821 - -8CBAFB5678D47121DC5F0CABA76F0A1A306B22C19B86C883CCA36F39:\ -26C2C7533B8481560FA3F226:\ -9D59713C92F96FA1CB0469662541540E:B4AEC9DB70912EAB15AF012552F44BF0 - -7AEE2EA671EA8B5F25E99F000D181CBEDD36BEE605D35BB4AFE833CACA:\ -C0C7FF94C3588CEB45619BBA5C:\ -B98A22543794F9DA5C3419BD9A1FBFA3:CE98649597F858EF844335E5DFEF4198 - -D0FE64F8842CF1A4C0750C6F11F8364E72A23D80D139900C9883CCB64090:\ -924A4112C3B76FF98D45355A60A4:\ -4AFC52C6B9C20C594DDA2CDD347E72C7:CF05111017D4C887CD55CC02B02DA6FA - -CB869382EB0644E9D00736793D5E19A56799CBF313F87EEAF28B7D997FD34B:\ -B545B07CAC05C6ABA080EFE09F1B58:\ -4AD8D6A4A2E9A16C690EF49ED125F92E:DA3EDE56EAE31D96839D85633DA0BC87 - -E267E3C9701672235AA5B69C6491BB54CD490FE8F99A6668A94AE6DCD94035AE:\ -DB210878188D2D0A9E72BD7C674D3F5B:\ -4D3E720750529D0F513E92763E59A31A:7BAB929338BF9DD7315B5398A892F3F5 - -861567E2AD28833FE5B6F4D1A37D2D0D5984FB4EE2FA0AA91F7AE9BD7D24231BE5:\ -C1DE878D368F80A87C15BDF8A40026FAA9:\ -42353F4A310C9A8AC8C8514C792E0D58:B69A8E451A37C12FF4B9D3F4E0CD9D22 - -AB6C088C4E0C0EBEC2BCBBC9A98514B05A445D563FDB50BD62EB2B9C26958803A297:\ -9ABE34A69F182DCEBB766EC9181F2E083382:\ -2D35319C7307ED58372CFB6712952547:3BC55F69931ADF01E3F72111FF54942C - -C3B6CD7D76EFA2E354C4E8F7304C7075E18768F4289D7F3836FC8DE15474C7E29C58E5:\ -65CD9E4A150319445A8C66F02CC3BF651E9FE1:\ -3D837364406414252F703E8CD50B2A1F:212D386588C4CB78F08E3756ACD637E9 - -670B848D3BBB52E923AC9BCE4317E68D7962C73F3D467FCF5924EA7A3C6A49C815D7265D:\ -B3DEB5D5B958DFF8A64ECC1D146E33BA0A261A89:\ -CBA99B5D4C96D127F5C5B4A8A3697E5C:C25D5468AB2185C08FB97A99DF9522AA - -7682A2E42D701828D7DE633AC10F944CE42E00EAF52316AB023662E4D8A7FC16C1D06F7ABE:\ -D1B17D59C7BFD0F0E77B8EC21AFA78018B2ACD11A7:\ -CCE8F486487E7A451DAD16CE2B6F96EA:4086D1BB1594D50F0CD79A36A4ABDD70 - -F083A6CD239631E8CF3055108CE5BC491F57DDB5F57C3BAA188A12DBE43F1670BE36BE92241F:\ -A7AD209830FFCB8A89F2E90A5C4F57E3AB63559A0FEA:\ -C4EC64DD6D082CB6B2D363D26B94D136:1E5B2907658557BC690220BE9C2FA860 - -57FDB6E005621F3F5A23049803817D8B2982C20C3504B0\ -BAC825269431C3CF68D51A0E349E5DCF:\ -F6C8C495B93A0AE6F61EBA1773F05D7C2ED4B9F17E5E16:\ -76A0D567CE9CECED93B5B1286EEB3354:E1510EF8C5FF55412D29FA1EA758341D - -8BC73BB8EEFB46E742DE9EA40226DD48755B1049C0D01E75\ -47FC1A6537B61CE2F3573496F291D016:\ -F7012F6E6E938F7529E7905ED045D0558A5B168B3C6C815E:\ -E8280E1F06468BFD47BA6CB54EFB2A77:E3BAD5B3FFA50889001F143D8B959B73 - -AA1B16CDA20C35A84D0B7F89C4D6E9C061FC2469080F1AC929\ -8590EFDE1B39474005CB319B19EF3CB9:\ -8B8631197B30C7370B7FE540567D2CAE5C8E6053DBCCF75162:\ -7F52829F60F32AE6244462540B99608A:7EA0E1FCCC8F585BF0AB36BCA3871F22 - -6B2F99D7840808EECC6CC70DD6EE11038906EF6EC8C8B49BD121\ -B5199B440625D00CB38C327597AD9573:\ -F650F5F428CC5BF6B755CE90DC86F46A7DAB41B1CC9E8243A731:\ -A42FB43E3BAA8E309EB6FCF9ACB34F7A:432B0037957DE2D72FAF75B1F21CE296 - -FD24E4137BFB0BAA260C5263FBA35BE28E1ABE1928F2AA55C192DE\ -C841A8D08639F4721712E1CF737E9BF6:\ -0146825F3EB53904628D652D59F003EE604971226BA3BA2E8F3DD1:\ -552308A6244E28838DDDBD913F4AF76C:A3E7709248B9036A25A724533661258C - -52F6DC00BA21BF0A0718F5F931822EF23C94ACFFEDE0A7BE28E4DA74\ -6246F6B89B5899001060A42D0543DE26:\ -CCF9C55515CA3C5162D3847DF2C6B318314444CDB8AF9C34E985E351:\ -D209AE9F0273F4173E3069A004ED1DF6:B3D10EE41552B1CD024E02EBD3E53CA5 - -4A87AE20CDD8058A3507B1BDCF4AF6737D38C40F8AEF647DB8158D503B\ -E3A1C394C7438B171AB4E57CAC2FE274:\ -CEBE04BEE25C79D6167B220733336A5E2D7C27E888359C3D6F1F01E981:\ -FE034FBC070D9E6386757A01978134CA:EC92F768B9E0F0EF7C2D5E9B2E471C2D - -1D8B38719B5032629F5AB5B6EE59C3DD22F7A48735C5710802DF28704836\ -F8244F62E56E0E12479AE6C6EE0BBA0C:\ -C3D1992FB96CD9A6F3668EB54276600EA7DA9E9D3639C7CDFAE556D851D8:\ -9115AA2A4463971D0A8A84983FC60EA0:D4B67A7253B0AB1A7EA5FFD47D51AD0E - -6D030D5AECA8239E4BE536F5B9886AC6F38FF34B77909FDFA81C030348B701\ -3AEBE5C0889189A4B2F3F2B3E06A5DC8:\ -5BB719AAC1999824AD9AE817491AE0924A56628A895DA88EAFCDDBF5F32CB0:\ -4FE3C9F9A56391C9102BB12774CB0707:165E69A0E7C648767516516A097E1A58 - -C932628CBB4E53FCEE5C585F04BC9C08::\ -6ABE1356E6A4B484E454BC488E108979:B29D87C2BD94CDFD94DBD318309CDE9A - -C712CDA7CB6CAE9C067FB1006B33A740B7:61:\ -AC7A66CC944A177467DD30EBFFE24344:4034E0C5EF7B49AF710B8B86BABAE767 - -4BD4FB492AF9296BD50B0338A4D80BFCBFAE:5EAF:\ -C41CB4E2208A2AE49D59313AA3852A50:B23B3A8E850C41DC30448304C9E2B38D - -944500DA2B82C64DB63101760FAD9B04B7B5AE:8D2848:\ -CB5972D3FD65E49F000D5754664E4209:69C9F9FC392CB8055E4C52BDD97A05A4 - -EFAF16EABE3320C8C650AD585DFCBDB537E4E5A1:B29B9A22:\ -F57E5FA4371F40528911EB3168011F36:ED4B8BB9B6635CA38F871E4122B96318 - -F48C1026C094968A52983AEF848644390EF0AD887D:1D74EA6C4C:\ -13EBD6907963AFA2A38725D1C584C40F:809E32023528D14D9C626A114CD65D5F - -8A60BBDF08C42353DDB7932AECEFB220D692A8E8DA2B:44C3EA4929A1:\ -D5E9FD2260051E900851974AFF447B15:467F03F57C4A071F4D4CE237950CD86A - -BD6CFB5269FEFEA13CF4E32FF4CCD483A27B8A7A1D1B79:4928D4FE0CA3B9:\ -8B5E6F2B0EE6F1239D9BBDB7AAC91B00:7F9E64B73FBD80AE06A88205B425BE3F - -F9A4A1646EBB784A59D7CFCA193B3E9C2527FD92542D0006:44F885030002B7E4:\ -7065E368FFBDA1905BDEEEA754C0D5F5:35E4CDE820A334649BB9679CBB1E802B - -6896B0857D444F64787D6C61B71AFD5DCE6B9B143A1DF9DADC:5EF4B47926F72F4C43:\ -E6619897C6063BA60CC799EB1A05729A:D8F3B9E8F6A746EA5BBF1053EE5D96D5 - -9F75767C335CC510E6C814189ECD49E8841F84558AA47D491263:\ -90E00F618EB235500F89:\ -B64A720D683731BAAF132D6DF42600CD:98CE0D42969D23A5FEB158330167BDB7 - -29CCA4206E1C37A5BBF518BADCA66A13C0EF15C354C63CDFBBBC1F:\ -4F332A5B8C25A9113EB2DC:\ -FCC2E4AFFA189E41FCF0459C26DFF44D:CF12F4E161270BBCB33065C56F17A16B - -1BE9151414493D890F745B9C9810C915C679A03EC472007E07FFCBCA:\ -8A000D4EE11C4E34F75745A1:\ -29A10586F8D97606B9E41A679C348050:1709BBA10AC8EFEBE43E20DB95657CBE - -DF3DAF8B27B621FE4A580417174129C2DEDCD57170522DCF082B122707:\ -F5E09BB8E5DBD03E11BCB8D472:\ -CC41B73738199B467196B9A5D6D39682:2904770A9F30EF7A002D8CBCE5602FB1 - -F9A7C4844697FB986EC79D855EEBC2EFCBC7720F2A9FB9CF74213A49FDA2:\ -FF6503CEBD39F306CCA42EEE8508:\ -9BCD3AF2077CECB7A2FFD54AC8082C23:0A2B880DF94646EC4C12907B0016839B - -8ED7662492F58987CE4FDE4229EDC77BF0D32EC9D8F9B048F7846A34D85A3F:\ -449CCDB5F645CD9637511D12F0A3F0:\ -506B94A8633D7873D6C4AF0C6908AEFD:4D4ACB024110D0D74721F45A11974A61 - -BDA3847797F2B5D97A2E4B1F307B865E4F56543BF56C50BBA1F6020E91F592F0:\ -A66868B66D2467C7216A6338DE8FC825:\ -ECBBA42D11A978A354AE97A093300139:9869EF068E56CDAFC131E79FC0B0C5AC - -532AA827573A33F5B81E62BC9DEE898537A8ED67239B80CA3453B71020D864D90F:\ -037B870E75AC9115506E09A0230BCA03AC:\ -B72999FCFBA184A8B895A9B1FD3DB478:C5C2ED715403C2C20C62E5172DE9C3E4 - -FC2B9B937B6A7F4C9A0DB15278C5CB8A7BA136430DE5D201C66C50689351FC237BDC:\ -E71ED7DFF82A2797EC693B182D313B08C6B8:\ -3DA9289752DF9B669A9D8AB66A71D441:50CC6B776357E19F700ED0AB17966354 - -56CBFFC676262403ECAF1BC51C3D65E5E1CD293BB5B12546C264C79891160300842334:\ -3D4300526204967051D76410E3143B9C17CD80:\ -37AA0C11E0EB1F53AAC3EE8500318553:9489E904DAC168EBA47C264093F3C0CB - -B24D05663B3C762D59AE8B164047EAACE87695B82AE57520E0C87A2E6D1DCBD4407F4090:\ -0A22454378AAD07A5A541ADF20D54664BB7310BB:\ -8ADF49FC3784012C38A95042CC968544:4056BE9AAAD879CAADBF2E68323F24BC - -C79E13FADF1F05C15D7953D016FBAAAC7969DE1AD696F802231D449176C2DBB6BA56467B27:\ -FC30113613A67D7C64C63A8F8B664650ACB6DCD00A:\ -6D5300B815CB728A792086AA32BCBDD8:39393D0074CC8BDA12DB86C8B756D224 - -FAF932FE8F4422C8BECCB00EC76DA79257C56E1EE4ED314A0A1075D952CFB97621D4CF7CFE14:\ -0F1A561E0B0F7C0FD152926D0F90D57384D7FFC38D4B:\ -D64CA6972E6F91E7B2A00108BF0C183B:1BE98EAE579D3E2C10C2030F85905A5B - -1F09C21297176C1788562A8126B83E0F0CE3FC15309E6C5B46EF97E56AD125:\ -966B82E2C328FDBB167D085DC029A6:\ -274BAD60A536DE7D916F95CB2175AF9E:0B1B20EDDE48EB9A5E68A2BB28CC614F - -23DDEDDEF95C0B28FE8D5B305FD83D52F442D97D465CE637A648EE04578106C0:\ -5A899A3B0AEC81C95D7AA595E2FD72AB:\ -A7B1C1626B3ACA26D2C216EBD618B630:A1506BAB3DED749A67192F4A16A1F5BD - -7985DBCD7922D326F9C06DC90E0FC7F518A5B7B11C155EAFBB9A708D6E10CF9440:\ -A73151592F0952CCB9723ABF53269882A7:\ -F3D05C6CFF898C80E2FEC0CF063A7737:8CD0669522324E946D0EE793A6693A9A - -C843A2352EC2F9E40094A80D3C7B00D56F0F266128D4EE4CD2AA0EBA9FE98A21D4CD:\ -543D2E144B36DF48A1083735244C91FCC30D:\ -79DAE3A9A8D44798ADC660173CB4556A:C9A0A0A8E941B02077D56C08D130154A - -5EC8F04849BF9E61A2145BED2003B1784694AD418CD2944888848D03B16D717346359A:\ -3F5C581B378124D866EE6046CA54DB45993CB5:\ -5487234213607058995B0E949A6BECB6:A26DDA7AD3C8DA19922EF4D8C7308D1B - -7EE5D87A59A6B11072123E7B728EA99A0C89E3F4EC9D9E6D088D09C57F77ACA82B6B36D9:\ -0C1AABA9072AF4CA02D6AC2AD5B2329523AD8C7A:\ -8E9A279E45508D14A43293B14D3F5A54:694E1F6B24CB95F97EC78EA1751B1B03 - -83765858587AEA004B2D98A3E1841DAB06E251E5AB455B6E7434889B014BA4586ECD354880:\ -829F5237301335F035CC410BCE75C4C2E89E8109A4:\ -D96E6D0D53061BAD69902F08E26638F5:9C292B686A3637DFFAF9C7987AD03D54 - -15674158151BA6A84F7C8937712D65A5B4F61325685A19EEED471E2CA7E2EB43F15CC2DC1D36:\ -B9D5B9BD05F145CD977E358D799D637F093D797D8378:\ -AE3F3D269BC1B851DC7126952E2C8774:F91EF22FAB6BCC0EEAD54B6353CFDB01 - -4EC14FA09C85395DC42D807C64B052203FD889907B40E8\ -DBEC0AB58A1C92882CE226770FC4F5D5:\ -339431576AEE57FE6091D148E5F6CF7827F25C131F2CE0:\ -7CDA2113620FC51042594199C32FF1C2:8F8293D76789A6DFB1983BC4B868A434 - -3A1AFFDBF58441C6CF36D4E40A7D2DF0170D1EA2B99F53B7\ -37814376AA1BFE8B4E09363225EBFF25:\ -0ABA7C2506C0C304711B50BCC699B7C45F3DED61A794ACE5:\ -ECF144123590C83F4A44655005285576:43A532093EE9CE9E26BBFFCE4FABB33B - -7F3D6219C09BD6ADA2C02A8E7A6218E070A2D065F68BBDE76E\ -8CFDC872AEFCBFCDF237D789371BDBEA:\ -404C55DA8B61CAEA5ECDD03602058A07F28499944B86692B8C:\ -DFA17F19D8CA59241F34AF81FE99DFCB:6A15CD6F9FD462236DF66FF4609A803F - -A4140A86D0BC3A9383C19709D2C4E833F3474C8AF0C3DA63CA\ -6ADBDE7BCBE8EC0F11141C4D0E4415FBE1:\ -54B2BCC0182145BC510319425F6AD3B10A1A9BEB65C04B32DF65:\ -3B0E2A90CD7E438A3F5BAB8417FC8730:3EE79A1198A52B339091F3DBC3D340FF - -2718AB1822C8BD9DA39B479402449CE0834BC1616ECC3F1308A24D\ -EFA73CB7D1FBCC310686AECBE95F7532:\ -1A392F066BECDF3F15D95B92098028FEE4310A283094A3A81CFACF:\ -C4D21881ED51B0F3BD9DD2FCB2AB5744:B5D76DB3BB9EBDE3CE5287776E814632 - -1A6C33093FB3931CEBB1E7CCA95FE93B135F8D3768AEE395FDDF81A1\ -C60D528B0BF40326DD56FE8ED50F158A:\ -15E86BA59F0E3D5AE3A664967C1BC3F6022B8DC12986DB779273BBB0:\ -ABC25FC0AACA664AD9A3A4BC490952C6:2415BC27414AE86AD0C3E163369C13E1 - -585F73C77639D0DA807CFCEF82DD595E5F57866BBC2F619F49612792A9\ -6C2E4C739BAA2220F986801C95FE12DA:\ -7C9C82DEEC159CEB4E9890F0FCFF5010F9E574362A3D6D06B2147BD18F:\ -14440CB0C6EA9CDB8687291E181A1B17:6A2B104F9F4779DCB47F8FC8FB60580F - -F942097AE0852BFC7E5E4034BA987782575056C6340177427F61E313BC2C\ -A2CD299779B29E8D500D5B8F84D6CA5D:\ -7D4A2EE3D0CAEBC205B91F090E6195C472AB3C8F56587625ABA45EC236B6:\ -2FB3005D96D02881922D3BB1364912CB:0D84764913CCA18AF14C2E4F0E64053E - -3EAE2A7691FF14A55BF3364AC597A121FDA3816505447F6E656E6F90DE370A\ -B2F5301C67E32A4791273DC653CB9062:\ -8B64BB53067C0A54A3CE6747467225AD9E3C853FEC39257D37A9DDADAB277C:\ -368B378A91B494E657624D9FA8BFC456:5E00DB9DEC14C2694C6C46F9176D764E - -EEE5FB0FD6F649C34C45F27D661EF1148620351502B170EC1B0C677569FD210F\ -59C137EA5A5C0A:642F4682F88B96C3CF59B2E6FCD637AE208CF5C909ED77:\ -1F9CEB36B1C443E828722EAA6ABA412E:899AE06F96B7A644D73239A03B27185A - -A75638B27A2F4FE3582D82415D92D25C0B1619CCF369A212\ -D3821CD8268A2861E684DBF033DEA847:\ -9B20A4045D8350AED236E92ACCFD43608017D7CE19ED43C8:\ -923874D1FCA7C997C86D9C25F1ECD3C3:22BCEDEEB9304E3A48250861124B2AA5 - -DBE84456BCB905B3637422CA28EC7A35AC31EEFA1BF37A7487\ -8755F2FE39C2D2B2DCDCB2F31450E800:\ -EE45AD121C59A97B8CEBCFFF2BDF5DE934F0380DABC2BC109C:\ -F65DAEF41041E256EEF472479EEDD489:BCD3B49B309DD021D6DDCC989ADC3490 - -690F6EE8335B14038CE0C4503C2BB83B7A0198BB4CBEC743D187\ -F18DFD6D02E879B2FE69CD0EADDDB3A2:\ -40765E67929DE7BA3ADCFAD278046E20484408B14FCBF9CEF874:\ -6D3FD9D7C1194E1F80E0BD679AF74494:C9BC9838DCE17CE592CBB08B99A80007 - -D9A4B214F4E32DFCE30964284BBDCCD6BE6EE0189982ED45BD6CD0\ -64A073D0E97D1B750008C05466EF09AA:\ -45FF5A1365893BBEE1B34E6A127E4A73F8AD5BF102B15B346F23BD:\ -9CC43DB3093D0D1CA2965760780AAFE2:1D2D2C9025D9EC16DC9D72100D95CDA9 - -1978FD1154D9855E614E6916EE875ED1C938F9CB92D57E582D74018C\ -EFCF84BA0767344E0F4AE7D283DB8D89:\ -B81D674F959354838BED29ABDC7E3F7D8481C96CE99D67E0E4DE000C:\ -EBC521A3E388F3781C47FBA734245210:A2918D26125692FBF3FADBD7D8DCE4C3 - -43BAF08789367FCE02931A495923920B1220B3D5C80FAE8AE5D971C7\ -C325A84838578241E52E76B684EDD3DE73:\ -69786524F6287A494B81812425603368DE8E50EB1E437EB6EB478B163F:\ -4D5CA9C6C1CDBCE9480534C98659EFE6:8C57C41BA7AF39EA2DEFD6757BECB4C8 - -47D494E426676CE2F7008D773DECA0F70690502D89853406C6D7D2CCBA89\ -6CC0E0AA8E3F23E7F7DE8470305BAACF:\ -15C0756699C707CE22491F8EE3798CEB43F07A9C654CC5B0F6B1533BD430:\ -47E9F0BC4F89835757A6A0773483F0C0:6E33B1E8D0163595C62B4719661B49AD - -8F3E66BC1A646352B7F4CFF7D001CD9B86BB808E3A87DEEDA3E8B68C7B8315\ -D03ABB22AB91A9168498263FBEA483A2:\ -EA377982769604FE3A32422CBAD2D886D39B523DB489319FAFF15937C21E13:\ -AC558C2ECB2332C95D640B8A1FDE62A5:B1FDF8EEB1811F513010AA67D2C87B7E - -40310341FF81EA8A88D7E4A56587AF7C::\ -59A8A96ED2E623F4E9D947CAC18DC990:79674D1D63FCA5D519FFDB6C296F7082 - -8062337F189B40867709312776BF2EAB16:E8:\ -15BF347878D67E708238EDA55C887885:203E5B72637E6FA8A1073FDF3B20C750 - -01EB7399A21FCDB387D25DF865AA6BC1C267:72A9:\ -B896C67E8B41B87260D02A552F6308EC:5246679BC7FBC5624A8DB7CDE1297699 - -5F88883DDBE73A2F42C189785ECEF40C2840C2:015060:\ -099DEB942571FF3B10A92A6E906FC2C1:C2CF13025EC6D16B82C6284DC779ADD0 - -71EFC1445B39BDA3653BC6782E63CCC3972BF760:D82B67F4:\ -29C312A40B053890C346F9D28115EF8B:1962F49E4AF7703CD8470CB07373A49C - -8D3954997ED9F3520F6ECD1C9BC47DBF1C6CC57D26:504F42CE2D:\ -2988D5019BD60E616400FAB5477952A0:5B4054DF62AF337A438CCB93CE99C0F7 - -24EC9189DDB36C88F3FB33DE3ABCE099E43AF40EB1D8:611330C7AEBE:\ -561DDE748B1FCAE57C3DEFCFDE0271A6:83737F42C2AA4BCF18ACE248749007CA - -2A9BA364F8E7F57EFAC8109B1E03227934B549A3A0078A:298A24AD7D6DBF:\ -7BD999B1F33A36193E4EE6F028299388:BB9687C2176C6A4595F56A4272D701ED - -F6B6A2F6E1510711ECFC957C93C68919A5A45EE3D0B2AFD6:75FD2D40877B8432:\ -6D74EA617E714D793C8DB9395A49C63E:F42A025EC9BF043EBC317E44AC02761A - -0341E6D787948E8BC9A17F8B9A59590964FE0AB06987334169:0FB90FB34C5B9BD476:\ -2FCA567702AF585D40A48AF2DB191901:94FBCA24E072339981E6E6DD82BA53B1 - -2456A0634E033EB2C782A76127638297E61DA31BDA1F54909D3B:B3990AA14BEDA81F703E:\ -4A15134D809FBBC80CF4B079EFC6D4E9:E27795C82349622DEAAD1A92CC8AD116 - -6ACDCF1AF0A6C75858C37CB6320AB22BE515CA582A1F72DFAC1097:39829DB0BA6AD872DCAE5F:\ -B8457C4211064A0C8B73983C6EDBAFE6:883F1918789BB528561F00C8FCAE27B4 - -A215B0BD9C58AB3331F78C0EB238167F27B1AFE1EA4BD87CACC5B300:\ -F6C41B2D43AAC7F4F0DB482C:\ -1827B62D763ACFA140874AB706C80FF7:7BFB0171BF1C9E02C666F7B7413FE359 - -C2AE1B5AF7059EA891A6D1D467AE9817290A893586356F79C7381BF177:\ -9E10318744C56A3008A5EC8515:\ -1649066C2B19B5E549F90C0E0C0BEC53:AF08F2BF3A7904FFE4340889208D9E36 - -4F26AC6346CB5D7A8F8AA5FE8A3F721ECC63A3DA914B1AD48B1B93D22635:\ -60F4F38483E7AD0025500B8B437C:\ -FFFA2092F276F4B3FB5961F4E8059C6A:91FC5F8480E26C2DE2917EEE1CC16A1C - -EE5529B4F23A6D8B6D4A6116F512D755E38F05295A21E9C6B5239558FE06BF:\ -1589266048285014F882E3BAD57831:\ -94A5B81B06729AED640D236929A28F13:B7183917606167755AEA5814BFD04554 - -F801A572F43609E21B1B2CFC480CC255B6B3927C2B14205DCBF0930E388EA229:\ -EB0E42B7343D3A6EBEDBA8A6A049CE77:\ -95B69A2A04B2F33C552E7960EA802CD6:8E6E8DC2ACC7316AA2D9104322DEBAB7 - -F880860816D3A071426469345BA44BB27D070DF896D9AA2581A1D89689B56B9668:\ -D8DCB87E15D3BEAA03F05B2C77AAF23535:\ -78D92F1F74591CF5628909EC20E2C4FD:9B43126E01BD71F1189E68C2909EF708 - -F25661B5CB948FD1B2CCA4A7B124DAE53BBBA8FEE464FF95109DF4D1E02E4604426F:\ -AFB23921379CCB087180CD8A614FB6FDB2B4:\ -B16386FE78B6316264C22DF9DDDCAB17:FDE3B3C8EB2448B8AEA90764A6B91858 - -A900370A2EC7AC2CEDCEAA2C255294C9CB46D6D97131D8E1505F7B1C4340F843BD1CD3:\ -71F1F9A2A4A33361417CB1A99ECCD83BEE148D:\ -77A9689AB5DDF5645E678C57D87D507A:21F3AD82342933DEC7FFB603EDCB9064 - -BD005D094AC438EDE11B7D98482155DC8E86C614CB13D2FA0CABF8D2631988444A3E5D97:\ -AA6AD3EB14DA4E60BA09A9638DCE91CC31A66830:\ -CBC59EFCEBEB74619CF0AD465B81326F:5B80D015897978164709E279AF4AA97B - -57FCB6852E72126F5DB7B311D1CFFD5D879EE6E2013A1FB568CE1FE61A82F712256CE617C6:\ -A5E672D7BFFCADF0F12C81B2D06DA016C252D54522:\ -FF38036E82ADCD2EDBBCD4C12EAB802A:58701C85F1CE555E6F6B21C14066E33F - -A11936A7930617BFD935B7B380E052AB245B5EBAF26C8E7E55F28B9B1FFEA3BBCD3224F037CD:\ -A80EC62DA758DC5378B0F4E98DD8321C1D7E59FE55F4:\ -CA603873A7C460A7C409B58A365CE212:B05AC2A4444F7C766B9AF4C49849B862 - -9DA94E8A4F0D70643357D8D8C9B31D85::\ -69A8B04FB205D3FFD56C34E2C76E0D35:11262418D091320D2C04C8D0E810F751 - -7AE167B307C2F4DF79F63CF916B9BF1A58:25:\ -A3E94A0B4499F368B968B7C6FCACC234:025F7513BEC5B9744723A9FD4B7522EE - -C02B328AC966D363578406EC6781732A0441:E954:\ -FA133478073A08E890B4E159B4920BBB:901D53BCFFF7DD75AC0F1E3559078953 - -250BCF631D446250F8837F8FA83A6BF5386C84:E2FB3E:\ -E4F79E765765409D324E1B1EA414D227:FBDA962D22F40DD772DD774DBF728CA3 - -203D92FC604EA0896CE956A5DAF9EFB62714D238:373F1A06:\ -50070DC0D5244E49CB9C66AC7057CED5:7ADC4F5C39F9A000EF14B52653CF2CA4 - -757293841970FADFE86782CA41EAD6CEAA2EC957C2:EC3B7CC743:\ -103B1080C15BE0AC6124A0264938A10C:882023A6D7A67CB1FE759D39F2647C02 - -59C5C5C3EAA2D728B32BCF1B49E4C18870AE4C2F7098:BF1B83377790:\ -CF665E60D491E84EE5874AB04FA9D38B:A8021B4DDF9C63E58A23000D5A779E29 - -93C5B53F5C534BC3ADEFB928D3470DCFC8852C5E24BEA6:70CE6AB07A9A8C:\ -BDA78F4BE0174F8A04C5DCF1865E307F:6020C7248A4FE110BFAF7A702915FCE6 - -61D5E9CCB1E8A2F1458ADD75AE1BEB7800D6A37244109E83:C5814686F6429BF5:\ -55A89D0EAE5316F685F890E297E62AA7:FD97541DD6D93C9B5B822151C4BC4619 - -C818A94252A8257FC51501B6A67D4D008ACCE6A3B09E1B84AE:3D8F73596B10934BD7:\ -C9F99830A1E6B5BA8D8A1A48E7C2060B:5A1811DA7C2C170B9F7177AF04C287CD - -D987E31D050BCCD469D18C44A28640371A867DF44373D517DBAE:B8AFCF7A49212AD45FCF:\ -40E64886878D1D3ADFEC046F61D3E81F:FEA453D7F80C87C786D0E9B1A44880E5 - -5F2827FEDF63228EA08BFCDEA50C9D5D904D71618E6DAA63EB9C22:A3CF005672C1F2E6E1983C:\ -1B3A82403AF3B423CD1FDCC2E6714A28:8670E19913B19969235A5C093BF44657 - -E032CBD49F0D644C67A352AB9FB1107242BE2579D1C7A45D08B44DA7095E577D\ -9A897967CD41602B8608C8670914C13A009EC1AB9857143FF6E6A0681D24A75A\ -C222FA89CA68E7994A969D5974B4755C66FA404362F336B3D4DA9AF4AFEBB077\ -F9907F9FD674B8F80470819A0C09993B768F9F5A22D8057C416712E22E9B31C8\ -62626881CD3229D5364A5C949985177F0D8A3D1583571931CF2DF2D20D893E61\ -119313BA902831:\ -7F4E62DFB140ED5C948D666A2919BDB42905A549A8B6B97259A273C9E974AA68\ -C30C48744C35D0E1C2364BEC5008A0790D45C3B6FC7C28551F9B1E0810C871D3\ -D5B94721EE1702B04D4D9C9D563C176382DA197E5641D375DDF17EEDBAEFC08F\ -A807B0961EB3466B00E309561F20BAA1FAD31F5015F2C6F2E444DF9E339F2DDB\ -A6DD71C490B72F919A38E7BA58A15B52757BA38A6D697C:\ -51AD5BEFE0FA1CBBA0FA2C648AE3931B:7ECC033824A49377190E1AA37C831FCD - -E5CC4E45013E62EE928B519F369BBC2C49FA0F4A7E99419E2D67721DE413710B\ -2BF0D011EC4483BFA796635544016321C284DCE6EABB25D0DC72B52DE5F6C48C\ -384F516F96A2EBFAC4FA005C8DA36DFAC06BDC133A3BBDB64C51C3904E8CB149\ -272AAD85852F60F3673C8B14C1EA06F8C45ECCF898531547A5B928F893874BB6\ -51599DF89B31B158DA2DF6FB811E059F15DD49569BF3CC8103322A21F089FB80\ -41B026695E09E872D82F1533E9FB88B6C6E8A237C7294F6F72751F06CE9FFE85\ -74856C7006F9592FAA80332E74F7AAB78F:\ -D4B2954F1C16268C7C64BCC8066668635AD9CECE9E811018F948DF1560D6D734\ -886C83A582AA31FF0EEDC714532F78AD08467BA7C88BBFC1D39ED73375AE67FD\ -1AEBA29D95D39CA3C163B714932FC29B763D423EC902FF9CA0D6D0158437139F\ -22B53CB789D85A4A3B125ECE41206AB75EACF527AEF5C34FCB936450CB77EFED\ -2D2BA5B603FF003E115E0D537F770ADD230004D2F5C721C05B851026FDFF132A\ -2AB8E02DB8E06CC93E791CBDF0279A13279EE51C6606DCC18CEDE789ECFAB317\ -B3:\ -93446B73B034B129516F1978092D9FA8:12BB0E1997CFA584B62E71B0E1886374 - -17355698DF0456602166D82D5399F159D9BD771D3D23EDCD6364A855067E2CE4\ -AAC59A671D0C223B9D144B67DEFBCBB2025580F83EB5BF4C0AEC626C7297001C\ -A1A9A0EB46505265C591B1514F75B17EADC5667E991D3871F6EA8BCC1183601D\ -8D80E24CB6A2C22E27AD9A22F5B745033DF0960722D1176E9A162DFF184D8011\ -7DFCE09B8F97ADD449C3ADE8F7F0B45C2AAF447536EBCBC610BA543C3D3D91E7\ -37558D54C9F724B3501A5AA24B2DCBBA9CF2FC17D8700B356F5733A64535ACF9\ -325B48F40E28BF57649B73C63461B4EC9D7163:\ -407B43EE14D1B3CFD48F4FD112CD92E4DF5BC3A9AD29C4A5DB5A0C4E6151E4A2\ -CC2890E1F943B0CDD3FF9FE5CC31CAAC8C8D5539B61ADE9274EBE0D53CC57709\ -ED08EAE64B9AB31E9952046683CE120F5B6749128127A4F51284CB4F49425836\ -4A421C96DCD0B47522B8DBA686EDB5E255FEF4D62698CC381C978766D9DF9C24\ -21B9BAFD896E73AB274E51AD3C078F910583672B1B336438CAEB9EA4CB3AC8EC\ -F382EA7CF05D2817AB79C5E780547886D8E0B1F313152BDE01C982CC044AB8F7\ -CCA274:\ -BCFF9CD4AB15999296ED0B1CC5EBCDB9:FEE3E4DCE4AE5EB0B2A868A9740B1D31 - -8571D4B7665B32DF2A17849408AEBC9FFFE73BB7AD18FF8BB037227C54583C5D\ -B7A28B87193F94DA28F45C8D2EEFE4F765B3C0EFB5A3C09DEB3EEEABC7C78CBB\ -120C68C13129E4609B05CE484F5DA5BF07C3ADD4996DD14CD7F2D34420CF9E96\ -B529B573A8376317CA02B47A55156AB51FE0C713831C3FFB5E0ED8575FB3FC69\ -24996E6FC9BF0E20F5E58A137347A7532C75F2ED45C33061D0D3455A473FCFF3\ -41C0DBB260E583D4F499ACBE4DA22A19CE8D2BE53541BEEFCDFEB028793A60F7\ -156ACD1ABE5EC842B3B1F8B8A6A8DC028A5B15EF:\ -4DC29DC34D600238E38882EF62C982CDC34DED3A7EEBC36D99E11FDD3D523A8A\ -14D74D61374F991AD71B0939E48C06A8D9F4E257DFA5C47887E355C435904E49\ -679BAB9FEA44B9C160C3FA444F00EC28F4CE80D374444CFB28A1BF5D310DA799\ -A852389296F153F6B44D3B034D272C42F6AC156AF061651803247634311DCDD9\ -6F056B05F7BEFCAB0B37AF585EDB9A5487B0BE77112390144706497823165192\ -1CBC97137A93BE85CA6DDE2948787DCF283C473A5FD74EA7DD971F00AE7192CA\ -2D29DDA8:\ -BD9B2D87090BB051842E21AC6A68E6C9:3F35701CCC901C7A01AE442ED721D694 - -CDCC757B0721890851AF53EAB7DE0BC2C0BABDFCCAE5ED76E01B1351E7DC7C4D\ -882AC19EDC147C7B04B6203B1F4AE98251E13D7336B80B35BD42D5549951E2F9\ -F0CB913E3999527888D6B40737AE5EB9AB41B0051612D08F956B157D409EED5E\ -BB62BECD72B92A553DFA52B185357BB96F74E04D63EFB0AA7B239154698D4241\ -DE34ADC79D944FD8B0C0DB24826C57CBB4847CEFAE328418925FF3D6FC6EF3E0\ -2CC580A2D18DA0F6FA0E3E5BB44A7B7D058DF60024BA4F9866E804E05DA6FA77\ -453DCD3008430F314BF10E70FAB7BBEBC69B07CB60634F3D251FCE93AAE69702\ -010E5384D395CB82967BD606F9E686D3832C39497F1A9DF2DE621C2F92C785C7\ -CB0BDEBEBA5C4F1C7436B0FD931C9B245B8D0991215DD63F32CA48345EC64A89\ -68927310CCAB1E4B48813342EF6C24F92595763D2E5969F960C23D682A38AA4E\ -BA7C5E730FF289A58DC28762D79C15B249A0D31C7F6A7B07A41FB78A418429F8\ -5F58314D5D65F58C7C21B5657807FD8907CE47B5324C94D391676E86BAC4B9F6\ -CF870B2E1F7703BE8FCDF4E82C848712315C8C61BA10752AC59F90665C7C4830\ -CBA53E602292634422CBCA81D3C7CACA33F00FBF136358A921A0A7267D683A7D\ -2CFF3F35553CBE486BD7A4423E6F167D998930246EFF28CB33B042FC8AC78BAE\ -D594B5487D4FA8BC2F32712FEFDAA5B4A91085A5C75B43AAE3F5E753F0CDC68C\ -113C94C2030BA2C7E1C9C580592C8D4A08D0C46A0A45FE486369D72AC0AFFF21\ -5AA6CEECD32A781BC52566FFB25BE7975D724A825D2A74113A0840A00CEFA835\ -04C8DE918967EE89DCA99BDFEFF8C359FEC0023104BEBD00398E6EC01D38975F\ -4AB4027025ADE93B0BB7EF3FD24A9400DC304068221323CC87DF4A6AB69160F4\ -F683C6005BD32998B323750A58FC532C437BC40F0D453118D813178F332AD789\ -C2875EB6C3249C93EBD2CAAE6733093678F5A975A00D29D5931A1CA8FC07918C\ -5F232359F044558ABCC36520E75668886E9A8D33D088AB6F2B15FD571B220B71\ -4AA8D9B9014EE6EEAA0BC6F36EEB508B5914C1C13FAA9351C616221A7A880271\ -F84CE54FA9F377DAEFB738636C6D8C563F6D14362306D89F8EE8C9C3A13E04D0\ -01156654A41FF5405A6F8BDAC1FEA59EA0B6206E3E9364244E9C9DBB00836993\ -F7E19605E3D09B2918744DA5BDA9F396FA8D008A27DFCF63ACF7AAB37593BF3D\ -183146A59EA92D:\ -FCA1346D6430C5A6DF980E7E456D9296BEAA203C3A63704FADD47299AAC26FA6\ -63A313C7D4D86DB3717B31B6E9C44CA76E6DE3A8D053F77D276917D12B86778F\ -2A8A56FE63C4B1D43FE38A28A7D6CF1543B2BD1406B4912D1DA8FF492F76D859\ -012E5764F2083832EBC25A92982AA7DCDC64F0E2188110362A0F7F598557B286\ -8509EA781122AAFDE4048F7D2E37590B9B49EDB4CAFDEAF40C694D92C0FF1845\ -0803BD1A2567170A6CA6879ADDE0A57929932DF39017E89D80352F403547853D\ -4A435770AA6E7A161501B1F2E1566B0AE998FD7AAFE5172F1B466F508DF58DD8\ -38E548E253C2F968C3AA5BA400C6AEEA5FAB640E917B3EACC1ADFC4EA28926DA\ -6E6EBDC230B62AF3608597604C454AABF1AEB98229F72EEAA52A3947B35F2222\ -CEDFE4FE950EF2F5948955E0CFA08BC04E4442783C7062E19A9B284DFB4A6FC9\ -2953C7BE62B9B3F64309D612A961D2F7A5146FE184D2C21E6DEB6B6835DB315F\ -2EF91D90B2D186F5DA5C0783BDD97A63EDEA4471BC078F29F2FB9227D6C38604\ -BCA4956F751B644F786CD235454C983336DDA4F2E4341CD62FAEFD057184092E\ -289E9D9DBA01EC326DBE67B30A00E641DD8A33C1BE4F97EDFD94F26F18FC9D40\ -9A3ADD543BC986A987EE5C92EE42D3CBCC068C8B56237853B76BC2D0675F1001\ -99EE56D5B7DC7E3FCADAD1B81CA483E8AA0F730032EC54EA5716BABE76CABF0F\ -B815E470F262AFBC3C80755824F841CE08B4CF3AA02324F739DEB5AFA975BF61\ -8AA3D17C0680394200AE9B24A6DCF3AE90C2E931E50D281EECDECE95538DF6DD\ -30C85A364893794941146DE7F0609680227FB1078CDA2678B8F40D0B8104E8B1\ -CC42E814D5615D1675CBFE652B94E54E1397559F717B18296F2534F0291CA2F5\ -5F8A0A34EB674B603249C55EDDAAACF041018FB27DA7DBECCD0FDDF62C7FEC8B\ -09F6BFF45D0A54905319EE30C39A20059BB0B71857930524A2E21BCE6107596A\ -FD195E5A23B2EA77CBD8A78E72C8930E784B26CFDE2BF4800D0F4F6E16A8D813\ -C1366DE5E8585CB3300342A3CBD5B14320D713FE03077F1016CE7F2C76573F38\ -8EAC1D7604792A357C6CD84841898B62609E6063A5DF74BBADF3E7244A265CD8\ -D3794FD7F2790C6EE5E4B6266D4288CEE0E93186C8A5417698299AE34FF6BB22\ -6F0AFA618306CF68EB868F58C81726A800582EC9FD703F:\ -9699D979E8CF340B3E3F059FC20B6E2B:F6F4BA4FBCD17565D2CD939BCB03DA61 - -[AES/EAX(64)] -32E55CE0C3FAEA48::\ -C61A0851AB4E515D11525B92E2B9D850:C825FC7C4D539DC74887CECC70884F37 - -710DABD24D400F3B6B:60:\ -F956B879EC7F807F1FCB482B53623671:E64F90B4619D93137E6237929EABF297 - -[AES/XTS] -917CF69EBD68B2EC9B9FE9A3EADDA692CD43D2F59598ED858C02C2652FBF922E:\ -0000000000000000000000000000000000000000000000000000000000000000:\ -0000000000000000000000000000000000000000000000000000000000000000:\ -00000000000000000000000000000000 - -C454185E6A16936E39334038ACEF838BFB186FFF7480ADC4289382ECD6D394F0:\ -4444444444444444444444444444444444444444444444444444444444444444:\ -1111111111111111111111111111111122222222222222222222222222222222:\ -33333333330000000000000000000000 - -B01F86F8EDC1863706FA8A4253E34F28AF319DE38334870F4DD1F94CBE9832F1:\ -4444444444444444444444444444444444444444444444444444444444444444:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 - -6C1625DB4671522D3D7599601DE7CA09ED:\ -000102030405060708090A0B0C0D0E0F10:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 - -D069444B7A7E0CAB09E24447D24DEB1FEDBF:\ -000102030405060708090A0B0C0D0E0F1011:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 - -E5DF1351C0544BA1350B3363CD8EF4BEEDBF9D:\ -000102030405060708090A0B0C0D0E0F101112:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 - -9D84C813F719AA2C7BE3F66171C7C5C2EDBF9DAC:\ -000102030405060708090A0B0C0D0E0F10111213:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 - -D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\ -000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E:\ -FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ -9A785634120000000000000000000000 +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 + +[TEA/ECB/NoPadding] +2FA6A6449FB4F998EFA3F1679A638602:\ +4D3953E121FFDB4FD7F05FC74FC2ADFC:\ +F9506AECFD6B86C4E9D5D973B435E66B + +B4C8B417381DFC14CD6CFEDC0D83477F27B0B1BD842922D4:\ +7608D8A9F2BFFC14DCA6942B2867239BE3B4788D8748F314:\ +47BF1198D16C123C95496D0CCC9A5C8C + +18DE3130F51CD7A6172B3C79F6DF435B41F57D3B2D54DF7A436ECCE32ADB88EC:\ +58AA062B7B9EFAEA2E3ED1F9D19FA6F695B0642EA7FB6EB5C5ED914A4034134D:\ +3D8D2CFB7424BBD7B39BD9BB2C0CD794 + +64E00DCC29A3BE3695F2198E58EA42E323E99387CE99A0543F7594331E546EADD7163E62\ +5ED6B32E:\ +EA6EF6ECA267C02C2C98D03AED4402A85B8CC02326D1FFCF169D321F675C23BF530FD4E8\ +AF7A511C:\ +C1C1384840D2B15BF8751CBDFB2607CB + +CF70A73AD2C4714044C8953EA103DDD2848595C182BC6A703B2E6CB90E80357120AC671F\ +10C8060EB2A14451BD69C9F4:\ +FACC24C79AD55C3E2FDB55AD21F52595452E116FC526ED3F21C4386D0400F098F86D86C4\ +E630E638A24EFF839EB8AECE:\ +25EF77ACC4435B378B0A07AF35D7A283 + +5AAADAFF6BF18700ECF66DCDB2AA201A1B5C338422E654A9E769C0EC40982E2FD9A794E2\ +9951C6EF26AA3FBF41B29E7457B6A2BA4E39F75F:\ +260629AC2B3838BADABD4765B0BB6A65D34927FC51BD712A36C8AD74AF386422FC479EB5\ +1C5FA2072B4D4A3F259A761C4CDAC375E0FB7883:\ +B3763F385F9F53A76F59E9E9B8070886 + +10D5908E8AB77BBC4B6A2D89A13C899C9044E2823FCBA56FBE7312A7F475E16AB3B26E74\ +FA74390B5025C2399AC84EEA37326A6F8EF8D133A3E27EC6A01F97B1:\ +1421E0144AA1061EAA75F81B44E12A8DE1ADDCF46D4E29D636F17565AC1326B8B5E1F2EF\ +097E3BC22CA2FBB5B637E17BF164DAE5B8A0D503085EFDE1E36B82CE:\ +84A6AC5EDB9A96C8BA3BFF40AAD9ADFA + +C65601054E837A0BBC4D0A50CAC6CDCFD7EC9879316EEE2979F6FF139D881DBF7338DDAF\ +02F3700BBCD7ED67D605030187A588775A3604FFB20A989D6893FED3814179B336111DC4:\ +7F65DA6551B8C2A677054CBFA5BAC5B8CDFFE2593F3297B3C6014D8EE83B00DB0BF063C1\ +68A4C155705A7984BD961A0278BE247FAF01E3BDC6DF3EBA4D39A0566F59DBB3F1D682CA:\ +0B666EE6C0C5FDAAB1D3C528825B8262 + +73ABA32AA3A6D791EDF7C1FEDBDE65950ACA8E7CDA9AA303DAA259965726F7E54EE8E07B\ +6EC41EE05DF08A8030AC76CD419CAC55249E5454427C9EC1607721A0A8DFF4200175B5EA\ +B66D6A33CB1ACC08:\ +39D91242429514DB8B2715FF7CB1D12AE97AA9B31286E672DCD6D5FBF9FDF52739F50684\ +F629F7F8F47F4840E399725DB5383C4427FD920D0091B8466ADCE80AA86E945AB09F9999\ +DE7518991229A9DC:\ +6CFBA581ADFD1DEFA555D4B1F2924E67 + +A9956670B38BD99613696110B2717482945A798817EFCB34254271251C1D7912F966F78F\ +DD0D534BAABD440A80F75FF20C5D62C21327803FD957699302328B03F12F17A9D89CCE84\ +3227D99E3F223C2E1EB8541FA4DFFDC1:\ +27F0468A37ADD1F81E6C453DB2E89A741C4949D4994ED22D4473B40FE63642B0303933F7\ +4523055F9B2614DEB0A5E4BE8067C9EAE91C573C6508610FFC6CDE32DB8C3BBA9803F9FC\ +F1A1A3C8CDAD99F945FB9912BF38BF24:\ +35927642F001AF7BBA592C573D566B04 + +2AE6CFDEFCAB3176BB1D7C9125F75011127F87F068846B5BB17C04457AA795CAF2459C7C\ +351CCF870CDE051432CF0019A5C411A45979A3E318523366138501A8C167A05B959B4DC7\ +C8735B9B15691262F2828A22093EE2BC15BAA5CC06426663:\ +46594307F5E0E998848072D2690D97E32058FB1D4577521FE5AF518C325762D9F076B15E\ +77E04DCEA1C8A2C34A287EFC5F9A301B5FB4C75699A3DFDF7DB8B7EBD61D5BB2C1F880EF\ +CCDDA930A8478C7DD946A7BF9EA906F6C6C930DF1BCDC51F:\ +C4A3785214040158D8D9037A9D5FD25C + +BC139112FA244D06DF5FFFAA2E44F58F29AE8B092395B9A67ABB435610674E4FF71027FC\ +E2C3EB95F7CAF7E05DE6C095551AE224A97807297F64C87247A34BECC6ABDC900259EFD4\ +048D384AF5481DE995C8ADE6FA7F982A702A44422EC022699B783E7EA57B7A2F:\ +57D854129FB358772683BB1BA42AF91F7E945F1BFF27AC4EBE6B531A581914E8BB57834F\ +D16A9E287544CD2840475155E49B9F6859D9E3D235D56CF5E7ECFD47D43FCF50A378287F\ +9F9A33AF0E53983456D75A58FF5111E69D768F25DAF721AA9C69FBE01F2430A1:\ +4A9F7BC01C835442B5F4EAECC8FF50B5 + +51AB05548D117A49B3C47D2BDFD681A9FA39A1D270437AF03D5557BD5945C66D44842890\ +2152A2DEC23141E4366B55DA9A5FFF68C6C67CC2A7446EB28125986E945D6B7AE587EBAD\ +8EA14B066241B54A6485A9878837571346E7C416376908B74AEB4C5D022080BB79D0DA25\ +B837D53F:\ +BCF3B29D04DE30C8EB5345C444E3FEDC5D34EEAE60EA71BC355F21F69E31F759DED7AA43\ +6EC595505E1631A52F5416A41A529F39F6958499E99EA5DAAD023593A78DFE9C443C5AFF\ +B6E4D9EEC22BBD66545A67FB8F39799149A1601DA998694D7BD65AFF19AD1326F4B988F3\ +7E555D78:\ +A076529A62A7C604739522583E1EC20C + +EE99893A9B1087AC531F3C5C67902E6EE086A11F6D28B3A41A0A692A15EAD2E0A43A3432\ +AE88E9EB54944F4138BA95A4E52240B3CC34E1EA6B764AE2703696493F45467041578798\ +1CBB062910A3DA1D39ECFEE971EFD945B44A5FF4C4140B5893A89F6F454F9568D83AD429\ +272832258D3D0B82B7ECD00C:\ +641C64CD007BED6BA89AA7ABB2BA478717C84844D06D0F83251B8DCFB0AA02FE8991F06C\ +DF5328B4195B272807B242A0CD51D9C9CAFDBCA8773ED2048FA25360601197C1A8AAC3BC\ +AA05B087FF38F53072755C1AECB169CA4EDDECAE1B580433DA6CB30F4A7E33D02C6E3624\ +982853DC5A77BCE8E3E9217B:\ +7D9FC06731D5D44E7D137AFE5F7CB7AB + +E687266A896382127FCDF60A3F271BD3BD21C0306B8206FE9D9F2B00F4201418A4DACFA6\ +53DFD029639AAE03A6675D3E2B4ABA7E46CFBE14FED665E0F520F110BDCC4E5647BC3D82\ +723FFE0F588062E56DE991922E9F23FFBF2E1BE91625A190210654E0B2476664568B44EB\ +58117317C6B61645C6907ACCCCC4BE949C9D3ED2:\ +0058B2D35FDED2CBC91D454AA55F93B0A249152B3A5C9DFBE907E639CECF1B90580907A2\ +9920901AA5278EABF189DB980372C2A804B2B301F8262840D45A668564C634191E027F69\ +1630602423B9069279FFC20B181CEEB2CA6C15B5A66B9FDBBAE3B591FDEC91D41413AF30\ +36EF4A99E9E1B728E901405E5EACBAB539BD4796:\ +3652786521A31CD6A927E608CB2A87CB + +6A5A797BFCDB31CA65F7A0D720B679B5C7CBAD92508E93C565E3AC94DA5B84C041D2A0A9\ +7CE0D138C2D48E8F613C36F4C9A9ADA0A32EBD5E346A0A76078D2B49E559BDE592977285\ +77714F3EF016A607D3426297B4681CE7FFE958B5750F8DB6F88916C5DD61CA30DC2CD2A2\ +4742EA7AF3886C792E1D94ACD6DAD21649A8BFA6F907121166E51D97:\ +1DAFC103EF64B21BEA443931DD0111CB06D5BF42D1824C4E3F3A7D6718F2911756D94611\ +7A12CA4974F9BDE4A99012615D6D1B78B94349216FC73CFDF7BF91126F017A9206F78310\ +6E636AA89EA986A4F4942A8820FFF0D0B151E7A74397EA186AD85899DA5AF661566A3BCB\ +3C7305DCD5113F12E3532B803E0ABA376B232EC1328F3D0F1F884835:\ +FE97F4A2874358EEDDE14C5A1DBA9731 + +A420F0855799B02E78C5A8087857A62E10F6448E3B02257AA678A7895EB9CBDED44D0ECA\ +ADD6ECB78F06CD65ECB8ED2183F62691FB42383E4062A5EA5078F146964F1DE275CC4493\ +04D319A4EF99A07C09B35F4C59E6AE9F8799C074C42BAE060E463A25078A61CBBD1818CE\ +C67CCB08BB4CEC9A4D3B146007C990AF9E723F858F7D63B81D4536243694AAC2F4C02CCA:\ +6AA3148AA2E4676C3ABBEA8B883560168F04843310B7871174C21F906E4049752617F465\ +DAA843BDAC395FED435C32CD2B497D2A58993282E1FC36113060AE36620AD606E0A32FD9\ +E143578188FD408D98C36F2A4134B10431BC20779195F5BD01F915987C40622D6D813CC4\ +8684D043AC74994B61F2CFEC89DA1A8A8C44FA82355508605324B20346B62CBF42649803:\ +5F5B428DB8D1FF5165F7C6691BF21794 + +50A9163557E25C824A3DB605486E137772BFB26F3D60AF6431065B11DFFB65B5F46B4978\ +6612857935365BE801D978A860463351EB37A62BB66EE43E0B348BF509C3AB450334DDEB\ +1FB04F829311998D026F7A66FC6E06795F7268D0E4B71BCF674E42E9851AD830243EF28B\ +854A2CAA00541A5AF0A3E05EA7A4B445264204516A7B824CC8FEAABA992040939E2D13CB\ +832A821267928B88:\ +E905FBFB19EA75D647CAE71A3E4AD1FD1150101614109A06C4BEE3E8CE5E677FFFDE252D\ +BD7AD0B65E9A47683D10B32E5EA1DEC50746E8ABE6B562054F1F60AEDF267308583DD209\ +157ED0013F91C76A58740CC94D46584ABF2145D441C7721E5C41A7B33CBE13A09D05A569\ +C7C0E313232282FA72B2DDF8107930C6A697D9C87EE66DA240658EC5254A4F8E4A99425B\ +A77E6D36557FD32A:\ +93BFF08E9CC32466F4436111031037A9 + +BD4BCFC5B25FAAE48AA8F4DB7FE80F14ED076F13DED25A3EF4784882F38838EEBB4757B9\ +BFB1344D422DC20D93EF2947B5D741BF945BC679BFAD074EEA9DFF9CCA6E49B6C40EEAFA\ +40733AFD8A21E26E19E9EBF66074C1102AD6234D129B589AC7AF71096C128FD94566E1C1\ +29D07E220FBE9D4DDA25BC71112D62AE335702CAFB7B46DFAAD51F6D7B4462A86400D030\ +CE96B577F0F8C43DB342E4C700C21F89:\ +1C2FB8256D92E620276C95006DF21ECD2C0DC26BF5752369C57745A27538200A5FBA2A08\ +B3DC4C6B7037035E96A7E4F97DF66B5FFF4D0AABB520A15D83FBA17CAA84641142044A75\ +F675637143F2ABDEA9631533877D3E77CA68B615A4EB9DFC4B0C27BB777604EC60950D45\ +31D4C6DA5412661D2CFF573DB93D4D428EC974904BDC6CE92B0F137188891DCAE497084F\ +D3DD3A9BF0991E7D954C473DD7075978:\ +07EB031C2A50E81BFD6150BB8E279F6A + +C12B1B0A8CCFE8BB72CA3C353F855F7F226DF0F1FFA791785506E972E19D153A92DEF0D0\ +82CAC0B4318E5C0C597638EC01204BCA002AE8BE1624AA4DDBC50759B8813F6533184181\ +395AE665962CD6BA22D82C1B4CD82CC4D2DFC07884C784398D596095B4ADF4A4CB5561E5\ +2C5DD85A2EC4642EF902A91FFD4FA73094D9A10D410743B82B24FE1149A5BFDAC8469D4C\ +74282581DB20BF4DB73321184B29E08D0A3BEB0A56D12AB6:\ +06F1F55E98C7B67858AAB0EAB9ED413B2E8D7BCFDD95FBDE16151A76E3E314022918B276\ +403782EEC2810FB10B8E6742287685675C67935217023EBE32994E1B1C7FFAF3C8E18EEC\ +CCBFA47DAE25377A1D38CFCF9FAF92AC99EFCA34FC70F04B03D1A2E8685B2CB2F513EA6A\ +49130BD8F220267DA4FB22E2FA02AC9B4F2FF554395BA7E0F85C378474E185DE7B04E01C\ +8929560B399D768267B352CA4BDA75FEA3B022B2790146E7:\ +0347E502FE1FB58BCE93EBB16AF1671B + +7BCCB586FE4F343EB7DE9210AAF5A5F81E62CBA5ACCCD897ED221CDA61E2D4F177A25002\ +F5E12AE2AFA0B19113485EE793F3C85FF14D7BC94B23AF502ED0118E78192CB4FD680676\ +194A99157E9349353E907ED93A869A1A9BE721ECC94619E26F120A87C1E227589901C161\ +7328D76F6B1555693ABD6F847ADFAB14CC936D3DA4F8F47BC5B77E323F23BD4DD2488222\ +45213A03CE770FB50D40E174606D3318BE3F76FB07473ED7034314E16567098D:\ +B42FBD0AEC444319719ED521AF7CC522A2F1DD69ACB6C6FC08EF1AD52415DDAA4E94FDE1\ +A21BDF954DBD56681E2E3D89C6725E716414043C42B0CC842B6A326CD70770881E047D59\ +B611B6595FAE0385111BA18CB19359AA7FD318B528D48348EB51655AE17B6DF79DF383FF\ +2F3AD856BA42598DC2D94921B4A93E87BD12490DE43C454B30F4093B30878B5BDA7D6711\ +F68DCFBA6AD0AC92804E15B6DC141A0D06CB962244700554B0BA4D399BB9D935:\ +5922D69B966C705B91F8DDB19DFD15C5 + +7D578CFBB35A1026C7AE1B82405B5F93366BF2280C6E6FB42EC515374AA2294534B1ECB6\ +7CBC925E375D4F6B2E1451CA1BA569D494FD5C0FCE09F9637C83276AE3E1249815445D60\ +E47CA8DD9EC7B846449C73F1648640299EFA82C2E696A0F9CA9738DFA459F8AE04E3431B\ +B702D4F6D41526DF1543016A8E0FB1DE5E5258FAC9DF77CFC07CB297BA2A2921EFDBB0BE\ +4F355197409CEB98BBB08BD24F48748142321E66C9791E93E8156D3FEDF7B3CABC0C4014\ +8A866D28:\ +50E48B13EDB839D430DB28787D20DDD4C070730ACF59E9B235F101557E88905B2B8766F1\ +9421718D82EBFB7FD8075D1239DB19BE2151782075A761A7A1B78B1613D95340083BFE44\ +9B502D5744512CAF2C33ACDE1F1B18CB53B152AFF2078319399858A3356DD710A1D181A6\ +EAD0EB9C1ECA868CBCE049503E372BF3B9364B275A6D68D92F2DA3396FC045A816C2E9FF\ +E3797538483CBC25A97DD93E7CC997CF7469E66FEF432B9F3C5F2ADFC55235710EADD2E8\ +FCA5AFF8:\ +E5C7B48ADB3AB291EFE88CEBFDC612D9 + +FF2E2C4B8BF3223B6513D612666415DA018A608BEFBCE8141F40EABE933BE55782E1355B\ +5D87FD7A31374EDA7BEECD24CB798A458ACC60ED063322CBCDD796546C0D09AFC04042A3\ +48E30D83309DA1EDFC0D631F1D1264D02812AB2F1ACA5E71076FA681BEEBC71C0104CD63\ +807C1B1C5FA543A2F30D903FCA91B6E946923FD57E1F1396B33E4C44F057693AA8413917\ +002C185FE0E54C2E0FB478B324E7237C6F4A5B439C2B52E1AA4A190263F5B6941244919F\ +AA826358C3F5055A1F67AB4B:\ +44FC4977E72F10AD62AD3E3FC7D868FBB09C4B7CCAC299E9E299B3FD5DF116C837B5D985\ +7AF8F83E97699F021F673679296444F96EC481F2C71DEA77E571DDFC49D9E453235A9BC9\ +3DC7CF60B209F305A2420830777D4B3732ADAED70B55406C777EA7CBC71EE2E58F89FC1D\ +4A1AD84A80B8F57C958D887383EEC107D5EA2E8297D75D588B24C8E42C2AB11FB21322E9\ +97B11DCB9AD7C825638BCC25A04E7D9311F24638418095D28259C74E718123CE597D2204\ +1CCAAC3612D803335DB4E21B:\ +A830EC3F2B6EB4C27215F68C373D51CB + +796E00B9B9C314F46A6FC4D30E251CBC99C0A7EC1012D4C08B3C709F8C42A0A24B52AA86\ +A8B4EE6C0B40B9AA749751222CE2E40E97467F8E49498D3EE24BCA8C3F6271AAD7AC9F69\ +F56B6F911B8840AC28B10DD63EAB8249A85747F5B97CF2BD18CD163BAF26D57C8E5454F1\ +62BA6D9758151F53D3F45733C3464836491C28963962FEBC6985DD4BAD90418C5CC02758\ +F59E001179888D5C56310EF3BD19660C98B40F39618C12DB9DF20A1144E4D88F5849F2A6\ +19903B91A4F88EA8CB0448B2D02ED413C71619EE:\ +35D5A3EBBD297958E923D81114240262166A0E6BFC0C42EFA099C488005ED84257FB7432\ +4568308109E76AC28EC059E7F8E612C2F8639C4510F996D311581D898E13DF6031385A62\ +0C5ECE9FD0745C7E7BB28323A16186065AE236482CFC37F227C99B6EA79FDB095D2E13A0\ +0CEDF8D91648CBBCFE9A72423485899CFBFDBC2CA6AB2CFEFBEFB38522EF1CF2D07AC68F\ +29819E17E202AB863F0878713F1CE248349E4139DC8107328D9907FC8F4987FC0392B120\ +F06DB28B7767AABC735535BB9FE18178B5BB34CE:\ +201C9CFDE22F6BE8FC881A4BE6862199 + +85BD2383419FFC58425316A0B1D0EE6DB75CEF29BCB06C55D961F1880C930C4536BBD490\ +2DC33C528957409269CBF90C28468F4260225B30C1A11611F524B4FC28FCC6B1BA85064A\ +CD5AB63686E8DA93A938081F14FF0D7BB4FCDB12B68F9A2821B397A6FEF87511FF67B8FB\ +C20D4338A00B7AFBBBFC73CB832346030920A463617A8E046E5B9BDEE2950DB7BA80BBDF\ +04230094F8357062AC03E277AA68D14AEEF8DC810F7BE6C51FB8866CC9FD24BEDE265184\ +EF7EE936EA79B68C9ACD37EFB131F2647FC501826A4F4CC5D16D4666:\ +AD7D51359CF9E854759CB435669B098EA48DD89DCDF882E2781170086EB679D6C45AC3A0\ +4583FE8BEA6A315CB59541E3753F800BFB186E9177A8E299A9F55E1D034BF8CC876C2F46\ +3D1273E320FB6B35FBE5E6DE0C3C205B6FC0EFB2A0FDED8C606E0422B0C8D72222318BF9\ +B1A3D7A0B527253BEC8C9F66115655CE3175828B6659352BBC461ADFA2133808D872BC1C\ +DC597A2EEDC72A1D2E2644275C60144F6C7EC00C43B6BFE2E4433A6F42A4CD2073528174\ +C466AA9EE0AB24429726029FF1834254B7A839A0D8D4643C131C1BB7:\ +271A2BFE528BCBE7A13214409BAA2E12 + +89DCAACBE537D9028953B0BDD28FCFD1E745D6D457F48F9247F51A8F6E9719D85F106E8F\ +794C6CA57247966AD2F878421C35528E95CB5813413B6E8AAD530AB09168A012D0027068\ +D63ECF4D7D4783BCE8014D34852F5A52C66461E15C965B8750087C43176E70E24FD0D4FA\ +83D4B9166C6311E328E08BEDAB29DBF554AE268476E507D7791AB3475DFE90CA3F3A3B64\ +07BF67E4BFAA67292E3ABAF6967C5450E17C2CD3C096C501B0180BA891EA951E99FA418A\ +CB72BE2FCB74FF143BABE55264F6B1BCCA83B81856544B843FF59D9668BDCD7EFC2F1F0A:\ +91B44C174E57C20AFD631C5B21B329A8B438C3249B5E0A4587BB01EB3C3770BDF67C16B2\ +4DE0DE2D61A1ECF3E00094BF562A21B6E2B9DD904CED2FBBA18A18A4228B958EDB1C3FF5\ +5BDE7D544DDDE97C67C1EA5E1FA4F0B0FBD2775B93AA02F4E6E19A43ACC14D022CDA7DED\ +E8B2915D8D4D0EDAB2718E56B25A6AA3C79B63E5DC03D57F948CE7D78A15FE3C0C781B83\ +B5B116816D55D660F0B6ADDE327231069DE6015C622E456AD01DC1EBF527D05627AD3BF5\ +A09EBCAF9392BAD189B511F6E429C1052E05FDAA558CB8D720F5B08AF5C2B7E1D811DB11:\ +8588AF13229A77FB1006467AF02D6AF7 + +A3647B24A430D05146C564F62665B74242A393B47ADBF341DD56BB1855C0DEB052A6AD5F\ +4661A45F5107EF138BF5FBCF03F2DF6CA6FBDCE61D91CC9327D476B7D96061A4EFE06D77\ +A608A78A716541A4C1B4A9D99B473295D293F37F6F3E982CC8687B67ECD9C8B999FFE97F\ +1F28F23531F600D2D91865BD7144186A53B823887FBC4E5B25A6F233386393E40D9FABF5\ +B4119E83CB614CD4D302D999AE00E85F78F22687BDC1420784374B87CC7EB772BC468B01\ +AD895259E94FE55159FB5F6EC7FB5B7B1CACCD09884327F174A60C38DB31D6A8B8925D75\ +309D2D2850FE4E8F:\ +5ED0A794F77048023665D3B9FCF108C2794D98C4472136EC491F2EEFE3A2ACB89DC6A006\ +7DCF449AF304E0A43ACD79EF1C8118DCE1A73DEAB3CA002390E2DE166F24883619491723\ +AAE01FDCC31FCAB8996779604A36F22B1C8E418054BA9164D74CA8ABFD0C39E31A0FE97B\ +C4796802957CBCDA7ABC8AAF298C007F401B56EA023D26720B5DC3C9843CA604AA6F820C\ +EFFF2A38681A2B18DD37450CB853F5A5612C3F7083C78DE65CDBAAB5983337672AC050AC\ +CC013E6DF3EE7AAE6EBD91D328FEC89407668B5BBB40A94135E071A9E20D0420D24A9E71\ +9D0FC72A3136217B:\ +BFFD749F285E2BF09E6E1CF31F485D27 + +5A52582DAA9B17977B476F718A030152C8F4A9C8BFAC2CE9A3A78935B4B9D7DCBCE4237A\ +C8B51464E33568F6ED94CF29A2BD367D38D059116C57EC69BEEDD67858E9C06420C082C0\ +D4C18FAE8B617EFE427DE7BC07BA2BE9BC9FDD9CD15232FD9A9B8B3B9B9BDD2F801B69AC\ +5EFDA6FB9E2204FEEBC4FBEE4432407894C17DB0B8E0BBEAB451B15A3AEAD171B937E845\ +1664C3A80E9E28F8F4CFCD2F28C1B116CA3CC2775632BBB14832C36FC70073E6FF462B82\ +6F3EB092504BE6A14E78AA2E32148B2E63BB8EE4B2D7BED5E8E2E8F025852F03A65DA77D\ +3F9C6BB6B373C90F6B0D2CB5C2C1AC0A:\ +88FCDB413A956FDF038C69A5842363FC82F9D3BDF80D5574DC0C6867F7EE21EA4CF72DEC\ +9AD83D5F19F9A71B71A71EE76645A153047825B5FCE892CEFABE49F6B0D768951B2F03EC\ +A4EC7200141895AA87EBF85CC33AF12EBF0189DAE5F6218F4E485873E994BCEC2E007AB9\ +77BD2C8C77792F2DAC0F29B8F8161B2CA99C4E81DC9DA37FEA73E707200697647AB6C73E\ +0DD1D837D329801A7B5F56CB137A1C23F5FA66213E720156C9AB67398300DE5F979BF4E1\ +DB8C8DF0E927EAD3DD7F44302DC9B39AFDB4F287672114288E24BAB76CA10200DB56A428\ +A671CB66EB2E4FE80630B94152B06158:\ +C0DE2ED5FE62A1B2973360E18660DFB5 + +BC0990F88218EDE0DE9835353BCF340C5463CFA55FC4551DE21ABFE260A8173591D44A82\ +DCC62CA063F395396040F4B09E4CE63BFBC1C1F725FBCEC1A129124B111A9D393D53AE65\ +330569846DA3FD18A682B192773A76649BFA999859B9EC844C6B4496981FA13F8F7F0575\ +30879998BDBF8D3ACF090D5CF543ABA1E9DBB72B6A48B85794BF212BF5956DFCA7714BC2\ +38E5BC3E785916DF9D27A0FB4A0A391314B072EECEACF50DC8693D5777C45E932F5C0314\ +A882ED43AFF657935AFCA0B3FBCF97ADB513C754BD0EC82482DAAA8497D26A9E7F4320AA\ +382903AEEBC83B53CC297364446664424ED246037F063BDE:\ +41E85AED70C8464E353FC6E2D5975E0FAF5DB17A8573C7DDE4BBE0E29EB71CDEB210B794\ +D0FDFBF7ED7254B1EABEBD8CE203225CC4C2EBFF3B5D5BC51E3010F9946289BA3BBDBE4B\ +E7C3FEFE7E7A390B628E29798E732382B482D84D7863CB0A85F6F3CE1072CAB120960D05\ +FAE3510D36C9718DB4CB4750565C8745A076A7BE89F52A16DDE9D32A42CD635340F9ED1A\ +A39132E30DBDE32FB28354C1DBE9BBF817481903BD6EA8CA4805D03B42F2D5000B43475F\ +CC4103717BA2BEC3E2F1542BF308EDA7E2C71956F32F50680415685E8106E701E3F5303D\ +79F03214097A4874CFC0664BE4815BAE2769BA2CE11FD663:\ +C37E924EFECE82E275AA6115E2E2EEB7 + +C34B10E6DD28BEBD7DE1BCA43D8AAFC65917C51E848703C034284FAFDB04DB3FFC0F3059\ +9C923C6BDCF006B47786E1EC68B9D9BDE22D39294CA235E43CFD42DFDFD3D4C49FD778A4\ +F61F17198851FE3923CA6DCBC8A6215E2CD8F24E110DCBA58A63058CF169A4CA4A8EA557\ +8030CCB2EB03C95871AEDDF6A090FADF44F8D43D7FD36987F31E0409A7615687C1D3FC0F\ +25796973E96A4DE0382D0965824E9A81677D414EE29EEAE3547BCE77BF9F6D3E6ED1526C\ +F1F51130D7DF5B6B34E89EEC7D8866486E02D5E654C920BC42DA3DF7F08EAA0681F13504\ +62B29792166D951CE94E5125FACF103D591C0E819667E42082FDFB7763C8C559:\ +C2CAE1A03A0B7D37D3FB79D98E425DAFDBAA0E2BBCDBD0366690C05D495014915ACEBD34\ +D320614752D0D667BABFEB9E3D5EBF5C1501EAD8D3C9602E6D33843C18F2868E237DB697\ +6536FE28B02233BAF37E9EC308A4E163ABCD4BA5422F92F5AECC38818371FFFF5AF0FC66\ +CE57DE4E0692B1BD82AAF95CDA6FF3C3C2F85CE16C54C151E32F146FC20AEDD4985E13F6\ +8C2E2224C49226545A32EC6C47974D2778184FBE289B14DCB78CE6DE17377557B92AC2DD\ +3C1102B74B2B04EC74BDAF85D2FC8F659F4F067F6C3679709A8F2BDC2429BB7F78F5173E\ +B3026156F2EA8FC510D5AA4482E1F5639F5514EEA3B5E979A0E54324954D47C7:\ +FCE0F56F8DAE31186336ADE3B46D6FF5 + +2112DE278B42F0E058EBE6BF868F544F740F0AB25C30459B6F198F74E8CB4E8B677F59E9\ +15CFAE5C208770C3AE03AE597D5B41C97AC6497F67837C20B5D2AC3F01FA5E831C8F240D\ +8115279D81E315060A77B5971506D7DCA40939A81E377015BD6BAE084861A9044271D2CC\ +66EAC30473931B26B5ADBB14471B32591D405B2D7C9F30A1B0280D21D5EF49A1D24F0E80\ +783D31E2A156CCA3F12C7EED45E471BA42635A04057D3BE56E31936E0BEF6E705FAE0E46\ +DAB18F9AFF3582935BDE554F650B21DF6DA8BD4C5CD75A58BC9FE50C03FA3217CE60DB9F\ +AC52A4BABAB8223A05549532ED8386F6D621E2CB97B829C0FE9886DC67CDDA9E3A0D19E8\ +70DC8E09:\ +67315AF4A1B112817E9922FB3FC8D251CE6BB7CC1CBFBFED1927A172D14B0C1D20A9E382\ +833306A08A3222FF0E11F19FDAD5FDF44911E46FFE688D0226B096BB227A0777B2C5F971\ +01A386D65CE4E71CA590BA8DF68DE85D50511FE1CC08F6F569B9D3F47D37A93BA28B301A\ +72D9AA736B464343DEC323207FFCE6AE59CF22916531B6EB6E92E5674C226E06FFF18F5E\ +9306835957E93EBAD84711E4B059A19F554E3CB0F08ED7AD6EA58730BE7BA5572BECC892\ +28FF83BC11F3036EBD8BFE370C7D74ED1FA03530E86DE89638CC7A1E79EB121F7DF32EF1\ +64AA1D0570FA6191FD88F7D09C1CFF5C55F3C62618017879DBBE422C6BD51BB320F7B5FC\ +00276019:\ +A0C7A1DD857747698B49D1E6127F564E + +[TEA/CTR-BE] +0779B5A4D94C4B572257340F8F86FBDC5AE955DB72E588CB3D8298FE27ADC668:\ +6D787EAE01A5D7946C8526B75BAAF2A8D1F13CE4AF93E469A21B7C53965A1CE1:\ +F580309FD46FC90ABA15E05AD82078A4:AF4D336BEB213C0F + +6DC828712ECC5C470541DF1602B85F4007CF93FC070CC7762D7956B7BB549B6372DBC08B:\ +09DAE7B36CB22B70FD79C64244E6E45987B5F7EFC8CB0B8E3CA9F43764807BE1027B7BB9:\ +C86E8F484AEB12370C20A3A0EE5590BC:13DCCD64DDBC8E41 + +5B65BD1306636A3AD2E0022E02E85269F20F76F45B136EFDF4C899F8C9656129B4CA8046\ +2AE80783:\ +E89A69E8F2D8150C05B56F2A4A944857B645B16280612F58FB89B08EE8A20EBE11C862D3\ +9A1A59A1:\ +4C55B486E92B56E40276A86483AEE6B9:3967D01A6CA67F89 + +311BD2A8AA6E97C4E84A3C322A53181D72A6C189C7B1FE6DB283BE9EC3193EA91521C1CE\ +DE7304F0DE4995EF:\ +10C9482E1BC5FC5F3E0204D721A9840ED5921483104A783D46B376E9B74BCAD25C5C4632\ +F523CA72CC6733F6:\ +2803FC9BAF7D0373B2D479046AAAEDD9:B91B7AD2875C1EE4 + +55243E865867E2281B3DBF43521D984804AD038D8A4D113DD1E118358EF1366AA82854D8\ +7DEC5C8051C9915F685F55AF:\ +02BEBB951E42063A106A0797227CD7CD037BDF9FCF2DB5405645B1CE17C0D6C36A361109\ +7B9D74599AA5614E90BA6046:\ +B45B330DC5589E6AFFE1A11C09C4DC30:04F4F13187E04998 + +37B0677F9DDBD8DB1496F75439862C17100C2BC735087B9A0970DA487DFEB9520B2C5B22\ +EC089777A710FC7C5EF5B7AD83199993:\ +E8DF3BF04F4EB8209BA30532885CB16F4DC4CFCC9DAA5D195A8F92BCD9B41ADE5B7EAB7B\ +1BCEFED039E3A3F8810C2B34A3E3AB24:\ +9344248E661DDF45BCB9B6E529B39431:3444DD3711244051 + +DB572CD1DDEBF0C06AE910471B108064A73851F460F3F79A303E463230162B99452DBC0B\ +0BE88A17765D4E317B04BAC5693A5B2E5A1AFFE8:\ +19D1415407B422F155D1E8EF9C99F2C77F68B39516D4CCD3AD020A4B01A64244FC0E3012\ +A19FEDACCDD64D948372A2D8FD2F7B7BBDBA8CD6:\ +215C4753906EE909902B163EF367BEE5:A9C40171E5946170 + +98E56143F834948EC76D2D3651787E8B6D1959FBAA1E4A8A8917091E626D3A7FCAE23E59\ +726A9B7E6808CD6245ADAD71EC52EE49F8B6983AF90165DD:\ +A2F29D9B387237DE529BBF8FA26704D4246C68F0C71FB986A735BEFEB239DF8220B3EE66\ +F0C8BD4B764BD4C8DA951BF3F0589315F5AE3E7F172F3F17:\ +63689A7EA77EE56313EDCD9092EE74A6:4FC29C5D1A03780E + +05796CA4B977B4D81B3F898ADB404805F6418425C6FA44C77ED6CF8B3A5C6A4D4692A3E8\ +A1D0AA88429C73DC0931BEE46EBDF759E16C975D8528EBE66092C686:\ +B8AB041041D2E9E48909A193956F9CA68D6ADADA5C2EB9A6F6795BDB751E704B2F9F3E6B\ +5531F2A2449C7C710367B4BF7F0EB293FEAC04D3C387B5C3D4F1F2FE:\ +F6DB0F1401BF9E04BC31F0E5AAE3B6AA:FF0415F250ACEF92 + +5456E7301B77AF7E4E571D7A542B4DA79A6C3E198E29B973DD482CE44EDAD6C8BA2A7C6C\ +044B9187C0920BF626E55E844C8746F8FA3748DA84A49D2393AB68294304CEA2:\ +86927873D7469420C6E817A1A9382FC03BA4DFECEEC08400E3B0995F1C695D2599B3612D\ +DE5017E0B2422F233C86859CBA4A038D2F9E1DD886720ED63365A9184B1EDAAB:\ +CC5B8B7E1D9877A5845D9F2C4070061F:EF786B15E7F3F602 + +E7CE6B54133D74C1D1F6370AA96F6993354E1BA145221B91B689B5A759F808D7861A7384\ +BAD3A192FDA08A36E9287B20188DF4131BC2D47457FCD3705C0D510A565A6E7D8EF7B22A:\ +3F1DA63F3BC4BF2691FD10D71CDFEF4FEB29F9E3C918C432AA7A7BC8F804E693B0A25F2F\ +935F9F9A8009959A118884E626F23FBA1C624CF719951940690C890AA05E8C87E55E3098:\ +899D47EFFEEB386DE8342FE3A3242FEA:CE412E40677E5BF0 + +F2369B2BEEB9FB44CA09D59D3C9A22E107E960CA7588066E9B95EE6926DAD5E91ADC1320\ +6AFEFDBE39DB95BDD77655C132FB108F4721EDF687CEE1258CF5C43D60F8EC31D5A26B02\ +2B925EB2:\ +EABC0FE834E386A647EBCACC5FE48308E475C5DBB7D18F404A83F50FC2F93CE75E4591C0\ +334479B0A9920CC3D9389CFDA9E2D532B1C491B0F1F3057C797AEDBAE51CCEDF72023556\ +D98868B2:\ +08C7C0A9B04684B49554E83499D2F277:7D16029BCE205DD1 + +2A101F89BCCEE248AAAF5EB65D9AA97240B9644FFA73305AEE2498A085262573D23783BC\ +442D6C296F126017403421AA5AC8E4AEE44E020DA81BF52DF9D0652E42F2768F1428C43D\ +D25E63E2B2FD7344:\ +E70DC7AC1E4A4E1461F6DC51F64B0C236F3BE15D5AAFFECFC1D094A4D69063E14EB4059C\ +D14481A26FF7DBC6BA07059856C2C764338B07E1C961FA56275AA450929BF62399B42362\ +9565E3E7C1DEB293:\ +9D923AB332BA365F20DA39217C7D1650:49B9FB1F976B6EC7 + +375D52ADA62453CC4F83B43BEC349E85119D9233ACBA7328F3009041FBB9E83DB788B79E\ +E543D93859404A91D0166397908BE510D0FCB58F0033D3884A0AAFF9348E4E3825E3D4F0\ +E8B7D592C7ACFCBA11C2D9F7:\ +27F658DDDD613482AADFD44E832C372665EC2001697602A274D84BF3C2C76A5626D84C8A\ +80306E31FD8748256FBA279732AFD0CEA0102EB103511CAB71458F881841A3D49A43D450\ +558DAE85159310F67DB2B747:\ +7BD5159E4DD63ECF90DDA801DD608104:7A60E38CEE806006 + +F81D39C6A1A977FBEDADE7F2A1C516FEFED8621E0C3FE4CC01DDFC4035EFB3F2DFD468EB\ +8899C9368A4DD48327EBBE739E6A68B063BCD5C03A896B47C1DA723A5AF8DA8629964D43\ +73F38F297DA5FC11597E0F0AAC6A328F:\ +84DD988BEACF8442FB917A80408164008BFED0C6B66A05E5EF5F46CBF5C126108F3986F7\ +336E5BCECB7F4645FEEE00F20511C52A750029CA31D869340170F30933E92A0DCF703EAE\ +3A7F15AA004D84358F76C4D3965E67C2:\ +F0DCB57019B3CEA07D6F8B81F8A974C6:FBDD2704EA4830CD + +44176AC9FA9B8502B675B559FFC21164366F73BAD09982114F21D2CBDAA15F88651EDE4B\ +BE5B644EC78B375ED58DB3A4D814A6DF7563F282E8FEC7C9965668039AB4988F6E87DC94\ +13AB3367500C6AC1ED5968E5B31F44F176B02F7E:\ +DE0DC6FBA50CA8E81E265781993875746F2C30BC80F682F085C644C162AED09718D09B5B\ +FFA421F8B26FEF78F222D55C5CFC71048F805393377AFBE94775057B432D712CE65B62B2\ +E48A2F973D3882D10BA56AA3DFECD37DBCDD2D57:\ +92BEEED6E43A5D7A6F6211C85229D86A:6B0FFBA1B3FAB3D1 + +1788E3C83C04ECE0D95D27BEAE329CB99D5E84FC3EF4A45575C630C8B946365467386261\ +CAFF1FB8C615C840E6EC28FB0A42C633B373F5AC79C32FF90F4883E0DFABF01963C78681\ +70CEA96A30B4DA4BFC1107E31AB53D63A9543373E505C779:\ +BC545A4E753BF6BB554B13DE4CD53644AA7235F2593BB0B69B11EFD66B3CEC201790271C\ +83138945C5A7347635F788CA0883CECB6BB4B53610A64E384F769F6591D962620B660CAC\ +0A587FE9212B5A247001B5439D62E144F91608CE39756FAE:\ +2A70897594FA8D00C8792ADCEB16BAFC:530C2B6E298FFD38 + +4C8E284F44D41B80818BDB68A8D57BD63F267BC0888CDA54AA48386E32C561BF8E3B370B\ +CF9615A74659846F476DD0FA6CDEA8FF11FFD3FE7D5BA8590CCC66D419E9D96ED3CEE7A4\ +6CF559345FFE61AAFAE1ADC3868E6C9734AE56B41E35B6D8A2316E4C:\ +FD08FED590AA383CE472B91572CF6E2244A897AE7116F0821DCE23223AC1DDC28207EB5D\ +DDACA086188DC78FE5ABAE43D3FC4F0F259C521EC38B8DC0BDAAE7F80B7B27DB75B00E35\ +E8A88380FA5205B002961BC6F1A4E81BDE84F7A3079F10F8CE644588:\ +85EDC49CF905E1EE9A8205C3709E1304:82E743E483BEC9F2 + +F33FE0DF117BA01A850C2DEB6EF8CD86CB65433ECBB079FD69831A06096DDBFFFFB1EA23\ +F18EB4B4F397F51A5662462D8DC8DA6BE49F9DA578A90E12C8CA33F4579BBA602EC4F442\ +2D93C5FA8E8EC2C9640C0D3A0F0201A5F3D57DA94A163C25E185F5F4089F68BC:\ +17297C6EAB5EF458AAA16A1F0D7A1EE3496CAABBC623F2127307EAA81A78A756E4373F39\ +1DA290357927B703EE1F0623A3FF7101CB78C3525C059BFAC4A3DF3588021953445A521E\ +415AE2576948B323F08E3CE108989BE73EEF7F00FF01C1C587B312E5D80C0D6B:\ +F207A0C6B1A66ED1D50D256693DACDDC:6171F470E638F864 + +59170FF4B0A175B7EF8BC2B2E0AB81AF6C994FEAACDE9D255606A1DC476E89980A092763\ +2819B55DE0892DD43F0D7CBE5C4279E6251BF5296FA03C8A2F0260339BCE64DE16155F31\ +97792C2379F11D102A2F7825A97A03D6A62C85C3A1C5BDAA18E4BC25F6C0BA43595D194D:\ +64EDCCBCA6BC3C6880DFC6BBD62DA90084AD8CEC2A704A7FFBEA8751F467BFBB5DADEB43\ +039C6F17FFF1EE87844C7EFA72A2EDF1EAA332CC4F281E5E813672C7A7AF4F85FCCBCB1B\ +0AE11F869382015D7DCD676BD4B482D175A5AE61730C5A29DFE7B14F7549A7DA12579667:\ +358CAE6A62C661EB1B365BB5C37CB744:4F8E99D3BB7E3057 + +8FDA3A1460325CF70E0DED926596E870382B6B4D99FE89E86CDB6DC1B25C82C5816DD622\ +980FFBD4148AD82196865644B90A6B282DE1B92A99CD2AE0E804FB330F95724CA5B45A2F\ +C57B0926AB998EDCBB63E61E8673FAB199C2BC83998B7F43E8307B57222C4D76CBC606B6\ +B4AE8D1B:\ +55E3B003AC093190C81300E08533A11C4C96D30E3DF4E030DFBB1D2BE741A8F30188398D\ +AB8198972D85B44948AF438D6BBD9F47CB1307389F456F35238B1901F03D8FAB0669B66B\ +F7DC10619D5DB72AFA4990F52FEF4F96576542B55251B83E7EADFD984DE5554909C89758\ +65B78A61:\ +4ED8501303B4D3F924D5C7C4097E57C0:2B3A19E6E2EB6CA9 + +3599E1DB61A7B8E74620BE5965CB0E160A69767048BE47083BDE3FB650D0BAC5532976F2\ +5530580B7EA047A346F5E8D413B07CA19928444ABC3A94CC52C7DCFFA3CE402F395CC182\ +7B13DA3B33E4658041E2F7393D90C27D928EAF9731A5054F289F736429D6644FE7906440\ +58309B8607587B9D:\ +6AFCA1CE267A3A90C6CF0179699DCB96BE1C42F0E7985C2D4D8D725C5FBFD9F6996DFB59\ +C0A5BBD09A58418E1151C1BD847B44D58384837E9594E445CFD87F8E324A0BB938838AAB\ +D0A496DDA178C927810E674ED0E36D257EA79743261F555B0E04E1524460DED8C288D71B\ +330F5AB0A13A6FBA:\ +C8378142EA256625CDF42F9EF7DCB2BE:7E12641A0C703137 + +7B902233AF687EB4D0B8711FAACBCD2446038DE3F41FA72805BFBE69E00DC9AC5936C848\ +1539C1E97DABB61CFFE9D492D758F8D8DDFF7AE764DB8D4D946CB3207123A1F95F7DF76C\ +F0BD8B276004C9D685C93D123B407A78BC8342FAE45D91B5DCEB7EE5A2EAB15CFA38F4FB\ +3586C45E7279DEF3A5376CB8:\ +5554A20E71F2C86C77A13DCDB065D01EEA0880BD648F3C17937623934C7EFC77B37733F2\ +D1E96BEDAC273954C3F8301A749D14CF74AE76A9CDBFE559AD9643BA818080E1D8FAC761\ +B45B48D0E19F51657115E8ACFD6E81211D890EABF55E06946CB90599005B535A6D274E22\ +1F7A697B92BCA34D1F09FAA7:\ +DCBF96AF1456108A9B9227ED94CE806B:05C03EFCE65A8210 + +A226BAC3B9FAB88446697ABF579D5332EE60985E2EA7065AFC56FF26C16CD4B944C7BF3D\ +C3CEF4BD9AE3000F17CB304B649D3A30776EDFA7D067D439A5990F2B7BE3FA5A6447D22F\ +BAA0683E7ED683707C30557557E2291574A76C68F32BFBA14E2CDE9E1FABD5034FFA38EB\ +A9A18BA405412D3CAC48D0A6F8B5033E:\ +B22F813952B9667C95028571AD9F8731A41617A9192671573DAFEEC9821B1A82296C8BCF\ +6DFDFE16D31F2AEDD69E9B18E8B34BFEF7D08FE47466AC0299F8E08922E515307E284BCE\ +85E70C7BBD4F7783653BCCE054BB82A14EE89EEFDF53C772273442576D37F90D5E2E14C7\ +0769F2F3ACEFF8CF1E71281D4172BF65:\ +2B4B352CF67C87C3397A3CFD44E6758E:C5ACF3B41053377D + +C85A0F50724680DF59E0AC198F7412AEE6734C05E53F6957BDC33A89E40DDCFAA4F1E211\ +C1E3390EFE49F299478DCD9026CC2E3B49F35E893ABDF851C39F76ABCDF9B5E3E4FA2B52\ +0966A4E1AEB36E8EBD1BF5DDFFF64C9935E89B75DF0D78D1B54D9FA6F8A87A8A47215915\ +70B47E091B016A381A3E76B3AE92EA014EB03905:\ +13C3BEE2154D3C4A9109B1F3E0D1D21CF47FDC283A7ECEDF2338FADC4F893896A8EF03D9\ +98EBB98FB732FDD1B11061ED6FFCE2613DE72AA898931F4B5471BF1B96D35FA467629275\ +5C1B77AD5AB0345C6B3E8FF05F7EFACC393762A075D36E88CC5EE1AC3709DA398E21F452\ +CE9F255D93BDF03AD42444C2ABBE0211C38F9F84:\ +81BF9C41D2404B0A468380F8CEBD5996:2EC2328185E51927 + +EA03F0920CDB09256BB8D2DCBBF5E0F9C14FBF0449BAC0AD02BBC6F3C5646FD13F2995B0\ +B6E37B8BEFC5E85DEEEA696E4DA351DB87D694AD896EEC2F810538CEDAF434931E6A69A0\ +19A2C73C3309FE7FF028D7A8D387CEFF33A63C4FA3669B41EF3DD8D7A0A923B4AF8307E9\ +072C32020B42D4CA2F6933486762E8E3286582FEE0F1636D:\ +847772497AD58F8AD957CE4B2D83D16C8F6F0E7A693DED94B7D1D11832078CBBB9783AAB\ +878CC9AAD7CD731E74D314DE0B9E9B9F65A279C05ED1382D26882F8BFBF06192E587CBBB\ +EB2167B96DFB3269B4BAC805288365849EA703E56FAC7F13805AE140E894B8E684642E73\ +BAAC18E7F0EE1637FC17C42789525AF0DA8D10DFFD7BFA53:\ +5A6F131AD458C1E9B3C004109CC78E7A:FF6CC874B337996C + +4A90541507A87188EB104184D464D1A04B622CD3C706B5A800B57BEEFE5AFCA521568626\ +7D2BB696F64F4311D33A83C553022C482EC939A77D6F2961D668625E214AA9081056643A\ +CCB0FB9C67892D20B674E5AE2036214C41D162C7B44E453F87659943088A8468BC127357\ +41B2F3E7F3DDED053B73377E9E9CE47EBE52A4FD503245CDCEFA4919:\ +D3489D41497715E8CA4B828E86A03903AE435C170FC4DC149D599832EA64ED7917F30E45\ +91151B08E46986FD94C2983AF9713AF602DBECBA6B9F9692AF43E53A3A04AD8B8E33E846\ +B95C8CDE80AA03D46C923137938937FD7A285CF322D23405F2FFB8C836B2CBA663C4967B\ +FE61DB36860B6B741826BA4F22E5393879AB76330545BE2B62389491:\ +B0221D669075C7DA04EA353F6712C7FE:386BC7C0AA935689 + +8C52A4AFC465477D059AA22CE8CE343FF273987F10B249B1A19B6F95A69B0C82F122B22D\ +D4FC9AD3DA4AEDCA876DBEE1AF12101B5CF065EF20E2EFA1B50349659F77DA6928BB5108\ +BD9226424CA31C7ADF49C4F738F013AA5A55380ADD25E840A60A5113B08506D71B702A45\ +25DF234AA0BC459222879DE4EF24B305F6B6E7D5702E3EE7320D5C1FAEE2AC70:\ +B054E0553AE9BE63A3315509949DC984F145DD24B152E6FB15D712067AAFF77733F7AA8E\ +CC4D60E47E4CC1305BBEDD7D572ACEBEC9FA31F3E701E2DD5885C1C39B371B6582D14AE3\ +2D31BC04976E3805EE3BBA6C727A82C8009C1AE39F866C6C5C4333498B32337E435EDD70\ +0A48BDC28A7918B8DE08E02A6CD3BA196C7236379C12AA86FFFD0DAC3D7390AB:\ +5771D7A711C92CBB93CB776D54083382:7FC654F95497E5AB + +18AEB9393D3A19E52A9F83E7E419C40E533CD2547C186038B315787C3F9616CE14A5A022\ +C2718D35CF6B54227C4E496E1552D392CC060B87E843313705797996CC5E73BF43141BFC\ +11452B209BE877D7ECE2A7A4D4C02745179B90D5E6A205ACD8BB01405632D1813E31938A\ +37F43165A1F1C5AC87A1ABD8A69AE655D4FD70DB124FD3420D700726705224533C9F6713:\ +51E70E5CFD39FDB62418893CDC05469738E3E144E4915064F2ABB82F0DF1D1147AC59EC0\ +01A5EEBC6763AEA4748825814E4CB5A90B271007EB8FDFBB867A9911E9DAAABA4D692B1A\ +D9AE2465210037A18E64A742D831AF8AB925B696DC0D18F45B80C0F6A46A07E3322E26AA\ +DE193F64BC2BD998F819C440CD47781A4DC21B831476145093319BF8FF4C00FC9E33DB25:\ +CDE4F850BA8D7F1C9114149084656B49:A6250EFEB105609D + +9DEB4E27C4592FD5DB48D3DD21DE22342C3F6F1533F288D8BBF3FA65E67A66854479737C\ +03F2FA5C40E0001FD84D9EA4604594CF571F03BBFC06668D12DF9EE61CCC0385B4532924\ +3D5A5D06C19791389E89FB54A6B85D005B64C08EEAE5FFD7DC1C9F1DB87B5C55D06FFCEB\ +1C9BDC3F78E5CBD67E06AE24500546B17A756F9A1639DF24AA77CC53B6893A31D87435E3\ +3B1045C2:\ +44C52C48BC865C5FFBFD05C2B27C4D2B69F373CF704A2E91FB2CB0D429B957A6EB3089D7\ +9182311777705987FCB9D8539BB2CCCFA1FFC8D49EBE6820D01F10597315E46985F4B4A2\ +160FD97BDE4E5F5C7C7441E06E089540788121B761340DCC2BA676670432C0B0C712D6DC\ +3B565B25AC5C31177A50499F716522CB5ED67E9EC63C73E6FC6BC68B0C5C7B4102D4F59E\ +79439CF0:\ +44738E1E4B7A442D209F2661FBDA824F:6CEBF2964385D443 + +15DCFFF177841397C5B02A1586B9EC69250F7C397DAA9C0C2B172234B18072B894ECEDB7\ +6F839878EBD358AD6AB62D387456AAE59D865969E9398326B140B1B16867847F0BB30FEF\ +787EFD2E7F61ADBBC9CF13A519DBA56907787269D5FEB735F88A4C6A313DEA440C4FE07F\ +C374E01C83D65CA5A26631C745F35875BD58890A066F82F4A46846937792C9E893C87856\ +AABD0DEBC110AD4E:\ +C8065C6F95C74F52907EF0E1409608E15C1D9C97980891B93AC41A6100080658C4F84FF7\ +70F0BF240B653B60A91796AE3996C449447E6E1E19FD7C48B8A6C6481C2B5F59262C895A\ +57B4C65E0549DEF9603FBECFEFE9AFA60A26A417D5523B7E47E5C04F07323A88A447803F\ +40CC46D57ED5ECF43D6F1A1BF48F03D0D56D7594B83BBE856A476E9A49ED457A1FC76314\ +0EE67FE5F77D0769:\ +7D8DA95A23D6B81028BB069A712AFE2A:278E3C3D1962967D + +47743B5282C40BC1D37C6842C7DAFE01D49FEEC11D27D212DB0FBD852712416CD392ACF4\ +1E1A5CAD44B82032FDAE4E94BB5F94ED0ECF20EAF9C68B49F9F0D0D3A49A377C18210130\ +44070654606CBC11E69959DFF4E975868399C4BD3A3CDA32ACAAC037A8AF3155F8D20AA2\ +B76285C6EEDB5AF9E31865BE1A86E5615F8E0CDA4F0DAA44DD3EEB1360C262429038E8C9\ +D43054EEA4C67E9C26504FDE:\ +F7081D26253675F37E0E644CF5FD2E2DF27B760A57A2C9753B2BCDBAEE6EE70DFD83680C\ +B1B4166DCE85F48E52943A3A7E83969F4D674226323C12FB306F5BEE80B96A8BF99BC497\ +9753465E587E9FBB43BAD2003C8DA5F99CE06B6D198D024E7E41576539CA2176DE8C78EB\ +4926CFA264C108A153724F49E38B2215641BF885FDB366FE4975A6AE5B5C9DE89EEBE3F3\ +6406F0169F09FEDC9D582656:\ +D798EFF93075E16619C04C27B44B7710:81D4628D9577608D + +440DFA2B6F45BA97928C07323E7639678ED1B247376F8B51BD5107BC66538ACAE5D9F692\ +4B9060AC5CC37D360F951D81CC2680213B48BC1FB392235D9E74076BBB1A7277E4B4CC6D\ +A3D8B011A31B92EA82DDEC54E3A982988E9823F343E6638A6C8A8B4F9FA1020A81B7B707\ +776BB4991B5C7DBCC9BB9D041154122FAE8F6690675826AA20C251B29EE5647B160041C5\ +DEEC1B90BA21207B39FD0A657527D480:\ +6253441E82759549F5791B82541649A09600395E37DA34BBC9B075E084C1C027D3A533D3\ +1187C4F0F3FC26A2DACA5F10461953F3F2D8A0C152A367C0E2B99DB3831FB9691C815290\ +2954A26C0D14AB3B8B7B5DA82450FDC4B37D6904F8835326D35ABA9431F003E867AC26F9\ +170DDA423837F657E908493CFC06944B359A42D1761DB68A6A61D9EF03DA83DBD0B4F69F\ +020FDB560C687377021C09977BC8208F:\ +831246376C66B8468E7A6E6E897878A9:9955251D87DE0D7B + +D2F7A97B171A9C774D0DF23173044F51282364ED0F373E86EA57C6AA726F313FBF49DA8B\ +F30411F4D85BB62CA06C577396C0CD74D8F43DDA49EC5AACF46D9D3C20F68FC8E36FE6BE\ +E147040811CF9C6EE80F3B011494C828B6822DD83F635C1AE32A115FAB35E5A7186942C3\ +D5E3A25FB2A2D18D877994DC2F2066DFE5873889978DBC5E6686F24A9D4F69AB8F7B9F19\ +FB723D39982D2C22A68E0D526B35C3782518E721:\ +4B48E6C50D37471DB4D311A3303722020E874C6A578E4CFDDE95C44507906ABC4FBA603F\ +0494AD42CE4A660BF4CA06BC7FA1084DE0315DB0C85081D8A06CB823DC876930F948D594\ +020092F3AEB703F95DF7BC94DEE275572BF9D6D6A6FC51AEBF7579F0CD49369A8047D46A\ +B9E47B8D90C4EE61A24536F638987E4D343E2D66DEA1FD670CA98AC284DEA1FC28ED522A\ +B1F5AD0581357300799413CBE6A78C9571B134C2:\ +59C571414163AC80C5856A8E8EA9A524:9A6C05BA3212D92F + +0DFE5D7CDEF8C0EFA80C66136189518199FAC9A459DF9FA5369D4F1AE4E3938DCF790F65\ +939A4D8E27CEEB7F7BFA098607DF2C300D61B00E4821B3A52150F5C38A9B12983E0232E3\ +05419FCF9D01628CB18D22C88E69091EFC8ED328317894145BD9C7488EBC4C7DAEB5DC9C\ +ADC240CF47B1A0A6D720A8EBABB78A2BA0193F2C1485C77DDC47258A8B9E34A4F4066C6F\ +CA22E44AEAADC6FDD6C398EFECC6014662286D3BFB339D2C:\ +248E8FED5CED6F9FE5BF2F5FE9D668757A222AD0525861FDF8DC86BD52C75AAB502F3ACE\ +EDF16448107C65CEC8C462C50D9918C7CE84CD7C1F17BC16625D4D9CBA7A335E8DDF31CD\ +F86EB9A2CAB4E6D46136F05DB0FC7E9811CFFE1DFED75A1394860731187B3F4D053BE3FE\ +A79693327F6ED98C40277D747D8601447D5F02401C0AF31DE0816310F81F83683E405AA6\ +4CC47953CD922ECDE6ABA6AF4378BE5691B78FB0C2918187:\ +B69C5FBC4525445638D618F669F82347:346955985318F429 + +4A25E4F0F608CB42CE5E8EC7B48A822918236B42D074D0D7C8D1209E4F68E4DDC9F90B25\ +4BF967FAE9058DE032C1084A1BD9645B7647774FDE927DDF1776D5F829CA436C9E8F5D6B\ +4689B592E7EE0ED9F88C12D1C6F30165406BCB2177859523855BE160E7CB477EC73AE50C\ +66F827563B4173EDEEB4AA6DB82B3AFFD9E719BB0701AC3DF37AAE2992348F33BE426B85\ +151D7581F1553A0E99C339BC407CBBCD3EC9D603D3F9E7110CEC5A50:\ +89A0DDA3BA5012B8D10F97F1546BB16AD2123FB97A8DE83EDFD42222EF62A07920C93B8B\ +3A123F5CE5EAFE1F9645975DDBBF031AFA61166C90E2A5677A07590B483CF6FA9D1597CE\ +FF8734A3D9554AC4C946A4551EF8698CCCEC3AE7142595D3130AB2712719595A6A143856\ +53DB4B52FA784D75869926237F43C8077732A4DEE1C66220226815E0E77F868C68AF4268\ +BDD89ABD6DCCBE42CD2CD16617467E188D200517FDE85989BFF9A751:\ +14388CE990670FBE1D821E677B829621:E13F97C3B492F94E + +E0592FD880C54A90F4A3FC3F1057712CEBDED7CFCBDC017C9ADDFB9714C044F1A5AA11E9\ +300F9DE1C15F8368B5DAD6DDB87BE1B6B2D3A32EE21DDE6C1098D2B84787E12366B8734B\ +37130D010A91A76CB6CB153EEE3AB7736A2D6EA3F6FC6072870F5EF351FEE32777CDA4B7\ +936A1062CFA69CB94405E1624E2D56FA06CFF4D31616B20FEECC2D2CEE58C81E3DD0EB56\ +3EA825C87914C1F38FB9AC35C04812041F2D81A32A9C8546ABA9BD5AB6E71942:\ +003770A75B796934A5C6C8362381B47E9DD791DD860AADBF9F71D4F76D648D210EA1F16F\ +513FE403B0FC39EB84354F585756E95E9C114679A1FF6F90A98434110CB1EF5FE540280A\ +6A82C56855E3A0C83FEA2815C4BDCC22308DF7769A22033F6B2C91ABA1F6BA83D03CA788\ +2EA584E2C2183A1E74A75F1E934E3E0ABFFEE26515528704B669802FD6CDE0811B98BDE7\ +120BE82828E0E67837EBEE0DFC30FECFDFD5B4D5A251571DDD8A42E46583CAF0:\ +8E0E06D39EA04A2ED224FAB12F875169:4687DD18DF082821 + +01A8E66CFBC585451DDC5BE634C7C80DA329D3DF16239DE9EDE1B6EA4EC912B5106999EB\ +348DF1009AFD0ECB16FF5A7EE023BC8C4963D52FBD8BBBA5D99B0512D772608746FBBF36\ +A362761CDFD5DBA5A0AE5100D0FE1AF4EFF576CB1370A4B403DF7B06E22DFC37B1E1AB6E\ +1152E0DED0F1B5867CE72F924EB3D5A122EAD315C7EF570DB199DAF3042937205CA05E22\ +C101527F9B9187DBA80461DF3A0855CE0D32A80255DB81327849901FF16061A52BFF8410:\ +0FA83C7A283B563AD3A1D91FD96E5033EE3BD79C786E6398504D2B152E8174BB1F743D2B\ +5F209A7792E89D24B0E91F9A8B19FFB2AF659F0826C743E85F469E31BAFC645EF27DF183\ +CD7AE419ED8D83AD229D9CAC3C67E8C6F3B722215D24793B3AF04283A17DE3B36E34BD48\ +309B2C8DFC5A4B55C0DAFB7EF0E40355485B89C381E9227A7080C2353D05E2E97F58EA41\ +A72E3DABA27753D44EACF8B9C03F21FBBD96D5DE4D36EF0EE7F8E554E1B468126F5F3AC8:\ +282452A3EDEC7BA6850A6DBB481F18F0:AC2FC317AE3C2DE7 + +525585F116281D04FD8C06E92EFC21C91E936913C1247CEE67727653974C09F768F31F07\ +ED1F3FDBD6A21194846E9C7E96E94728D640639C77B299102A8D7F6CB35904B00DB8455F\ +1AF65B05DE83ADB6F2759BDFF79CBEE13FC46669771CBA432E6F777FD5D9C879C5B891BB\ +ABB568BB541CFC1A8E567D718DAF292697370206F4B69541F9F44DCE287FF966B62431BE\ +A035BEB6C13573E32233A9ED5C50A0D71457FD8B99390FF345D22AD61B23DCD0A0464B95\ +310097A2:\ +CD13EC2531031AFD1B215EDCE6B60C6F1E9E8FB13D83B9DC28EE9F586C3C82AB7FB3359B\ +6C2354703093C883C489AC1AA24D21255E2BDE7BECC0F77B55E23090B18129701553A908\ +ABF324C917EFF7CAB5B12D6FD4CCD0928748A223DB90F66B48D79333968EF22502A5EA9C\ +CCF588FF9FE70AC2DB669C2A56905EBEA7AF56BCF42031F3866C77E1D62A793F39827458\ +AB46132868CFB8D72216BD41327B8473F24F68FEF8D0F46F339D533949B609FC2723D953\ +C5F2BC6C:\ +A36BEA2CD9E5D98B4B63A2EED52F8C1B:C2BCD83BF070721C + +47A0196C08AE929B236B36A04B7441FA40E69EACAF3F087F160709AF390C5769E1452EA4\ +1F4325EEED011D33B82454C7B6CDF6775E0809BE8068772E66EC81CC0319A7D27BBB50C2\ +B7D0DCAA8040FAC70BF3947B6E57127422E979242ED79608566A4CE9C8E0EF3589249996\ +601013B4A32D3784403D52F6E0467FFFBED8AC31E2C200F169AF68ECEDAE791AD6D4E518\ +624D9BFF90116F154686DA7342B071E9A9435FC4AE2F42536FC93D98D6DA6697AEBEB47C\ +94451522116467E3:\ +A14B00431D6BB8042C402005AF87709D098F6366527099B8044FEA9C173323FFBE5F53C3\ +013DECC92616652FC26B8E46E0FE4116F3A44D8C2E5F08B0D2B0EFA3B42CDD4809D2B8BE\ +DC6940DDA928B58D7ABC1A7E753AD1DE54273C87FB18E77D58C4AA1867C7B01A6F8C291C\ +3EEC5DDCE8CD3722749F3DA01C9DCB4E7B62F220697B5EB47538FF8FFD78E4CE949A0265\ +E8346D2ABB62F5537789236072548D8588FFF3D8DABB7AA51634CE7051E824EB4BF7415A\ +2DE90CCC264E2917:\ +52874F3F111082522E9EF5ADED117EDA:2455286EA57BEB7E + +D32975CF8583D36F57C092295D8FBA7C44722ED0F385C102EF12E5BDBAE80037C5FF0725\ +E6B950EEC1413E628EA8088B9ADDF2CEA379235CD62FC01762AF3BE11DC766A17FC10F85\ +BAD826E94147DB78EF4E0974D4566900D87643370A8C88F42471C2479B7686FE97332D3F\ +014809711124619D13644E5C95FD083212F580F9FA3E2CCDDC0DC33D782C1D103093B9CD\ +54E4A3113B6C75A7822ED24D9A422D719B26C21F4FE73D74012E81D9FF58F13BF1B681C2\ +9A94068A47FF18B9610DDF80:\ +C8D6A2E21C15290F42BACC559380F1ECB797306B7B59EE22E452F971D049D24FC7C21BE4\ +DA40A91BC91A2FE47E35CDA7C6A63BA7F0F38D038002093FB5E83CF52D197B9DBD0160EE\ +6CD4BC690E0BAD9379352400453E85424E2583B9FB7502F2918C60E0976722395BD8FADA\ +4C1726B249E4E8BBEAB59AEA3EB8B0D833FDD9A934D43542404633299FCF6163A4327820\ +2CCAF90CEE44FF094FEEAAA88EB085606A50E96C447234CD2F4A6602C18F71522D58BCD8\ +02DD3B97D5247F61AF099FB1:\ +1CCD49253B736228C454B8331631042C:43666BD9D4555CB5 + +BD15B15611F5D38034351F16A47A50C53F9952D35B0C888663EE6164F5F228584F25536D\ +8EFC04FC9BB0CB228857440875E320CE25534AFED42F830F7BE88AAED5D91C128EFD7067\ +A30088B1A3AB3C00FCC3C658262230AE7541DB9ABD0E1288EC7B2091050FF3935575FD32\ +D7CFAC6D599655307F530304FBE4E16E647AFAA0EDFA51F4CD075182F2B6D1E8B2F15211\ +CD52A996430CB634B099965A37B442B1E1B8104AE9DA9978412F53FD9FB1F24E5AD0A2D7\ +BADA6011C87593392A629E1E916CF28D:\ +BA61E2BFF557EFD75AA4E9DCBDC95E3D02C4870AC3604E5DB01C38C5E489254CF4B4D062\ +FEFBB3CCB044B488909AF465ED13785E5034DC62F65DA7E7CD0B53E625D9090123E8DD54\ +8E377C4B9AB085A4AC083A2EF1815F115C08CD8AFB8B814C17B2DB422AF48EB71566F8D7\ +246C2001795FA20AFA9DC6F76519CBF7378267A1262B87A98E6773E61FF3211A5994E2D3\ +FE2E06AB52BA830CADA7EFD02A36A66F2D4C559CCEE4769C0339E56EF3946E736B048A39\ +F41C0FAE0C7650B3486DA5A2349624E1:\ +A9AB5A6AD1CFC14030B05F52CC27D166:81F7271353D4D8FC + +2AFE5901D507A488E8729205EABCB8158347BE7FCB6C4FBC5F20EB471F00AEF1FCD46892\ +E679EA9838E22882B80B1D68258D24392C219F9106EA1175D54F5AA495B6B3E0E60CE6EB\ +6E1E892F2CED18DFC18D62012A4328923FAD58CC04EC70F832E3E1B8B2F1327414C5EF9A\ +57DDA4D40C63289A5346520B7CF4909B41A8190B668EB9E5BE78F55155945936DB2C20E4\ +C184BD2D3F6DF976168373A1E465E89B0C2ED18E750643932EF45DB0661ABB74088AA216\ +3C06A19E917D7B6F513FD1DB784534D624EE5575:\ +4DDCA5CC4014C19993D857ED57876B384E8E06523066A86A4A4EE4EC597CCD3F1619D4C5\ +124C088B1E89E969335BDEF659CD3E2DBB2FE26079EF7F5352991D26B89CB324234E2608\ +A77BA1B66BB194D4CBAE3DFD6B80359ACCB81C3E69CE2BD30BF991930AA22FF0A2D02A0F\ +460951DC829FFD8F095CB245AD84A152BC59DF1925B0F1BCA25FC2355AD25B25D821B22D\ +C0AB2749AB7EC0442AE798674D8E11A87257AAA2767894914056C8287B139751DA5CB49E\ +8DBACE28E2D9DE52C508089F8DCA82C7386619B4:\ +E3D2CAB6F748F35DD4E72335A0241476:D97CFD5DEE5CAA6E + +4541B90A451368513D4A09BCBE2CD48155E512FDF240E76795905DAC75CA9BE0264E5A7F\ +924C4706925C7CD35392FF441031EECDF0D9EFCE0E6135E3F4C1CAE57286552C4AA4D407\ +4C9F7C922B53D0F4CAAF6914F81123EABF9B012AB45C9AB989AD979A197D7094AF9A0EBE\ +F2DA9AD8E32E5FF16E14475F0694A79346231E532660E0176224F21676E304A32405775A\ +937E26FD3C9AF3A4DA27F2FC131717805CBACFB554AD1ED56036C18456B5C8211F2CB2E9\ +E34AA5706E439D1FD5DF049FD63CF2490B74998AEEF3D63A:\ +37BE67361D55FDF19B8AD1A39BA3DD47210DA5B83614B00A72120BA2D9E5CD65890C58D8\ +1A3060A39A4E8CDABE0D2862419BDAEC7695B87E2894FA5A5B05E0E1D1E6B35D5369CE74\ +1BFE4EC755DE0BCAFCC1FC160A6260561AF899A735817258BA86062AC698CD50913E0043\ +AFA85640C52BD8F1B979011EC8A20A5A0C52BD73552B2E1DF1481C62F2BC74E8150943FF\ +4E888D944B253D0CC82848DFDC709792A2FD987EC564FA6D47AC98C3B271CC0A6ED3FA4E\ +DD159715AB1972E45D51926E42E88C309A95494AF55C9E7C:\ +801D788845FC6152E33E6A2CB42A2A22:5F5FC8B7D6B6C3A5 + +9550E29D3D0E9483B8746D24A72396DD16DD31F7538548C6090950908C51E4AA9250B171\ +3685E1A7337A1D917D197B72EE8A0969D58CAD94C73A9B24A63620BE8152013669BA44DA\ +A9652C99787B338FF96C6FC00ABD13561045A1C25214695C990360F505D83E9FF3FB3711\ +535164E06FFEA4A0050A09D7134FF72A98C67F3BD73BF90E2CCAC943DB049A788E7B62E9\ +2C9178E433255A5644DC67B17CBC87AF2AA145B3E4B657F31D28B9282B0E6B343C8759C5\ +1457D48EB5880CF255B2058A30388D306D896AAD42EDB05158223FBB:\ +22473327F8358F22AAC1473C942B78067FEA10319F52A6969A889AB87A09FB2A21878B30\ +8627C0FAB3C1358C5C30F198FD5EC27B9FFF78F4C4BB97ED9804443C18C01470CAC1D730\ +95E8B9E2CE4E6766EB4DBE31DB528CAA80B01AE979A3FB32F056F54B93704DE4E45D0EC1\ +9FC8E571294C279CE3C1DAB74DE63C741EDC1AA7C60A8DC1EEDEB738FD415F22F9E42A22\ +19A1BE56404E8921D95DB53F7B2873908C9A7E09A7B80EB40968319CAD1FEF85D31B916C\ +2F0810CFCEAC1E77976D0DD2105F71E9625209ABB16E7CCD3171AF38:\ +540E936A8F7DFA7E1069D1ECB6DA529F:7DD8BE5EED8A3B91 + +ED1ED1768831FE993379B5EA6091A5CECECAA6A1E4218F13755A75CE982B5901191B3F6F\ +EFAC14A3D68190F66D759389A4B72FC1965516E16412E1DAFAD962A23420E3D108738D6B\ +F1B7D8FD2B6DDDBD590E88EFE3353664085D1BFB7B8E2FF4169ADA322530724388BA3784\ +64B2DF93893FF936274E53916490A4917CBA6997BDCBB9A84ED1E7543B89B64AB70F8CF9\ +3713FF08A5E8EF164E33A6C85205173E9D2E3B0D31E565CBFEDE77FBDE48CF47E742F56B\ +A466AA124B725840B56A69F2F46543C31C5DB8E926A7FD968B94606B77CF9820:\ +6F5F24233FCF42897405065C047A15EDB1BD4AC5824498D186E76D44A01636E3BFA6FD96\ +B0FF5112FECC0F7D5E754505AF90F25F91FC121E5729D77E569744FA7095BE9C15216DA3\ +53AAF508D7A0BE30C64549A1D2F092FA65DF3C29144030A0B3407DF0C80D29A82CAFCB3A\ +FC106FDD282E3E3792D034262EEC388134F0A0ED182D29AD8EE98FFC3FC18256DAB7D237\ +4A31F293F88812AE33758A35521093334BD204CD2F01BCA1F914B9C1FEC402AD226102ED\ +6C77459CE4D20EBC89CFDAF01334AE4DCC07D48ABAC694B86A90A5DF236BCF06:\ +C3CCC1F40F2234124E8E44BE4D230D51:7BB01E9C965EEAB0 + +A9CA7C9133827D9AF63A9A2D98F12E96708714F3DBA3F887C044EE50BF508A4759124EE3\ +748CFF9E3F47976EFEF9E9E91DB6ADF75F2702C277D87E7EF2DECBC60E861FEAF695E93D\ +F183AFC6548AB8F5BFF6C12A25E62C81196F3AD2392FC77326DD521D374F54865532157C\ +75F1B77AA93EB2178F6117AF2AF8ABEAD69C2F4B3FCD3F0BCF24CA460FB596E47C4AC6D2\ +873A96C90788A425400D8CF579733E553B9C38E538F2B1C762D6201EFC132E92ABB69121\ +30F22547BAA1E44FF487D1C4B2B06B3A4768A1220716C44657F679E1F200164046325346:\ +1F1B86628E58A2F6220B26B25DC7723D22B02F2E5E011672C354C6D1CBF272100F066893\ +EE1A9E353E841AC24D0AEF62BBB5480ED978C84BD5B052F1424D6238641C9F11E5787D3B\ +94CD7D866FEA1D2DBACB58DE1B6A0582B6C103926953B3203C94CC8B87F0630E77650E85\ +1449A3BEDE5B2C1678A5F17F920234238C0C57C51181E5D1E7B1082EA9D4781F825574B9\ +3B69FFB03BE688210B74B0A6338370340C90442709591671D19FED7D44795B97409119B4\ +CAD30C84B296C7CD76C3C3B8ADB8B273A35AE34EF402D4B22458EEBB1992C7A32919D2C5:\ +A8E311DC7544747FA09537683A4979FA:F010A1D16F896398 + +CEF68DB7976679BD69BC5819CDBEA5749593FC2754D2B0860A87A3B16A680E9B634C7A23\ +EEB7ECACDBFCA2FBF26AD3AFDBF29E98230B43D410F27777010F09ABF76C69E0864BA2C3\ +7ED9BE1C0E812154E570509F0C8F07C45A52E5FBB3DF015FD54BE20D8DEE69FFDE644EFA\ +4DD93E7C8A7582DC19B5E1C69FBF190E43C7EAFA92C67083DAFB3890C25324E3590479D6\ +BAE27E8E90B6F28EC39BFD46A73CE92F17609B596CD2BE34700E37E423CC9B9160304198\ +D917357347E414627D7BD9D36ABB5BA07BEA6C9302F73F370D2DA6393F3CF310B65BBD45\ +374EC60D:\ +C8848BBA822123ACEF694A77E942F57FF02BCDAF6E6540FEF7A075B890A8CF32B9372A95\ +53B501526455EFF2B764B5C3E8C3BB08085074B4EA0FDE7D4CE94BF284603423068E8FB5\ +E9252C73DE7DB341AB624D1C44E79ECBC22874A73743004B99BD6316BD7C92415C1F2A54\ +675FC2D26B0EAEF760B329A1BC24D140BA8F28000649F1FF43F586E2899FE63C133A67FB\ +C542C87A4369539D8254DED0EF157425B379CF6F10BB0DDB7937441E3C091602C76424AD\ +5E856550CEA7FECB24D54333C437251122C72E4D21DF23371B01D05E32FE1907F198F18B\ +DBF68351:\ +6CEA1E32C1732B9AAF2F9A85A9022895:FCF3906F4227113E + +A7A87EEF419C8600662C5CBA01DA56DF0CE6977991502A27F5FEDAF68AC26AA89FADBD15\ +63ECF3810643174D9A2B6E940E65ECD0FC120281BF9F52C0AF2F768924111941FF1D8424\ +788E75CAF63FE7389ED1C736504F99BF1590C5B970DBD7E0D13C283209435EDE2360146F\ +4F734A06F1ED649324985857FD3CD80C82E896C368E44B52C35C958D5CDB1DE800BA7343\ +412CD66274A97037667767FB7C7E4B95C261106FF3D34A209B998C38F2639F74631D1BCE\ +BA04A436D8DDE90C2A1A38CB44EFA7AC782BD5EAD9F3A5FAC879AA63F6FEA44FF967D709\ +92533375BF94C2EE:\ +2F7335F36D102EABA78F04185805AB6F88BEFAF2ADC84DD6DE9629E34A00D934FF017D7E\ +C8195B8B7D380FAB765646FCEAACAC912EFCF6E522052531D04255964ADC147ED533AE5D\ +5917ED43F7E21BA784B121DEEB879B41B2D00C8A18FF075CD810F8C5DE84B8E3A137E9D1\ +911BAEAB91402AD0461E58A58F45AC901B0B741C63A78C13C82B4709B14F7DB1B3896206\ +7F5A08DE2FA8BCD91CD6BF3FC17950693D0DFAC9CB1680E68D9C9823AC12B1F37E4B6C16\ +63F5BBE7D8DAF7961C3D7B37C34FD2CB02918785E8B7B6777704AA4F11CD974EABCCD678\ +4504A583C56CFDA7:\ +808372C49B7BBBF65386566C6973A76F:805EC1D405B86CED + +4F25B31BA0783DD6842D607CEE8FCACF6ECD2D5D6D885A230874782F2441ED47DAEF2138\ +E6EC20333CFF9671E008481F80986EB91A46C08C9D22D2B6335F8E6BD10144324726FD7E\ +A311573B1A03E6E6262B89D145B01BFEEF14D7904E0C53966747316842DEF71AD1144CE3\ +B8C08C16980A2EBABE9A5501C89CF0B6F610808112123A56FE7F726639A20EDF2C531D8B\ +DD30D9F4032C9C3F9C165634A898442C3EDDB0D8A63A855CE44E650E428B60C536918BE0\ +45A902B0346F232545B27A0C5EB15F79BBD1190552A68EE7C1D29D04DF1C70A7CA254A6C\ +D47BCCECE1082A20F35E7E46:\ +AAA603EC1AAF270AAFC06A43317B6FEB2398633A9D1C130F2C67B6C19E9C391C9396914A\ +BD907B1419551202E6228FC7E06FB78FF669A2597AEA85DD4A372FDA60ED0E3C30E872E2\ +AF2A250DBC6972CBBE00A5F1B5BCB7353175B5D528E32CB035460E12C8A3DAF3D1D4B25D\ +0CE9CA5AE3F8250548EF24AF92F4346A0C5716619A640100922AAE13C7824341A938E14F\ +E9D51AD691932421669D958C252DBAAF943C5AAF64C89AC8B381602D3AD0937D8B8ED413\ +2803C2C9F40838CF1A2064D269A9CA2266DBB642852DEA101E4E6CCB40C377F17D195FED\ +673F030484DA66428B3C7D03:\ +299F9BF1E1B34A0D39E6D49B67DF754D:A4C997CF160DCAF7 + +3B0CA636F9F507E2D9CFDF06B3D69B44A3647FC9D6C824C3C1FF9F31162E7A40394D9558\ +9123310056EF2B668F59B93EA71CA45434D104A91878A6DD3C4349D374E39B7A4635FA0F\ +0841824D02BC92EA6EFDEC08BF8566CCA111E478C569A96B9F7A2306A2CD5464EC4EB0FD\ +642E91A01EFC0CBBD08EB28B34D99989BC3D55DBB5BF32FC8C0CFBC3E5B89DF3B01EC4EC\ +8FF3553DA1714004AC52A2F14EA090B3DBFACA8A7664053DE14A905339D2952964DD501B\ +638EADC396DC05814203C4568D5469D7E3FADE0302C14BED2FEEBBEE5A78ACD17D0D4425\ +9D4A47BEA7C4935967125BC0F0E228A2:\ +253D1DC003D0BA2B60422354551E3684951A5B77C142061BF86EB95DCAA1FA06E2E047F8\ +DD94D3080BA6345E2F72478110899AB51D5BCBC6E16E564C407AC37A08F34108FD9EBFAE\ +560FB59A6A37DDDE8F014EB525AE9F5F63046C263721E72B6E94151A129A3BD446D9AC21\ +602FE0D150251754B4334462A99B7C5792B901E03AF71FAB991AAC8B9A75C29B2FAF3517\ +8946735608DF583B27C80661A53FAA4AA581B5AAB2F7F034707C9B812C9A22FEBBBD21E1\ +BD4821C4E45E3A072F8301435E238C7489B23646CDF37800C9D40CE69BF17ADE4992F733\ +F71C2273B37D1F17B68D15FE61163E84:\ +CCDDD91BCCA1490EF312ABF7D7EB545B:B091FE75641EF510 + +74CF8F2B03009D38E874C23AC4A01855EC591D2014AC96C5F6C4D0BBA42C8C3764A3554B\ +9D5D44D9FFC259E266DD0A2649B5D299139F2ECDC1CF7E286C183F74051B150674E9407E\ +C8A6E151E174EE66012DA6E2303AAF3AE7F677C17BDFD546589F52756CC02ED3BF4483D1\ +B4BF49FFEA82F0A9111BCA3C2B5DE08FF67E5BEA7D2E74564D686D554DD9C31C291ACCDF\ +76A0AE0ECDBB17A427D4223BB53592EE37E398707CCDD0AA70F815AC3EF6585F35A5E1AC\ +D44C511CCB79CD85B5D1CFF534B0CC7F89C41CB4BBD351D8FBA99EC6717A98BCABDEB16D\ +242F4DE41CF5BEBA4BFFFFBE600386FE55CE9F0F:\ +2747D5D76CC1A15D8D410C081DFA56049B7421A90B01EBCDBE9E31B70C61A58E0D2D5985\ +596520528D6C0F64063C3F2386F4ACF2FFF68CBFB8A7C78B97A573FADA6AB69EC728CE77\ +666C89250F9942F80FA653CE60ED9B65949D491A38953C688821A1C4B39F88A72AD5F454\ +4D002456990F1C4F3CE293BDC8DD68BF8E13818A05454565D9B87AA9F4FC906E4AC61A52\ +3C1C65EE7467B498B5A06AF633A37B5287854365DF96A2675A3A454A25A345BC1F9A0375\ +E091C6BC55054E2FCA011B1E3BA1C964A3470DFCAE1A937F1286031FB8435FD7487768DA\ +018E69AD3029A1C6EF4EAFC302EACDCE8A02CC23:\ +80EB0BB542D844F4768820077D8B81C6:E6936F2688231B9B + +44F6EF40CB3EEDE73D0BCDEF4009F48EFE4045B1422ACDA5111D1BAAD4827B33B37911FC\ +BB51A9AF5E6E4D675A968F119DE1A64075DC4670B92FB83AD3B44796522B0D8187EDFF98\ +2D38C7E8EB63AD3B838FF50662685D4106BB1E0424B5631ECF069D988C446CD2E97CEFE1\ +A2C3194681873266F5E02C7018715A3DA9CD927FAECB6B8AE6366998141ACF652B49353A\ +8D6B9A6238C331138CDC90659BCADCE15CED1615B96D050250E5196F88F5601F6B538226\ +45825C88580AC543DF13FB4403BD895000A2CAAD12DDEB584D70A0CBB8C029573F5A530F\ +9E5BE2359E6011DDD4FC25E32397CACDE24178D0E0AB186E:\ +3AFAABBA1BA4E009171471B45D465F449D2F0DFE600893F2D60F9BD653B092C7CA980C4A\ +BA1F15C08028835A341C5E59423AF6BA5E6F5B3C34E69CB2CAAB42EE3DF6B1FA10F2A611\ +FB4871AF01815135426D60EB540D13B9058F154D6643FDB28542A079DA0549E9C62BFB6D\ +CF3F6FD40175C86B2CAF712E42538F3B6C5C57024D36AEE3FC93B5E70CACD49776302E51\ +CE84B4075BDA7B37FCD1968A6F561F625B1D32F3652D8A7BEEC11A11CD8737A9C9F87D1A\ +4CCC3F24D201BC8C1CE24589313CB0387C3911C924A572237705774C89840DB93D5BEAC4\ +7F75E04A10839355A775A02FD417FCC2A0BD104E81E3CA40:\ +89D3696A74D8D4A751C1219C3D742DA8:BCA7BD8D3A8B2682 + +950F2F4CD525EEC6CB634DEE121B847F35D083523526D9E20E329C263EB892E5FF2ED907\ +B354B057101C73C094476768A225268BCAE04C564EEE9EC9D855E478E192A9FC22F12D44\ +0803BC49C5F20683DA0CBB09CF704E4938AD0620A4C40CDA769EA03C236B0DAAAD30B432\ +84486A8D2619E94BD1B79F01B3AD9E70874BD6B929BAB1121FBD585CA2C0D25B799AA487\ +7FDF222097CF0B8CE95593D0CDDACC418FB1734ACC19D365B410DCB94C3E64B11B5E1C61\ +DB6B4BF2E291FE653E2EAA266C3CE7FA16857001FB6C2259BE0A9157F629B6E37BA037EC\ +3A716293AD59C1A254EA4FC60DE1B875F40BB328B5B6CC148D5FF5AF:\ +34E2E8205BC53EDB71913053F33227BD0CE67F1D509A0FFC5F70AE3B59A7226811821797\ +26A242F1AADA28E15C3B04589D5847C762A36A73B7D0696C7393D5AC73DFE5DBA39752C8\ +A06BC4DF90FB52372598B43726849B0907DD640C9D0D4C9990D5F2FDC9F1535400DBB392\ +1C046556B0F8DDF88C46D8D7924E954B177B936EBE1961C89D5616761C51D576D60C22FF\ +8973FD324DD7340B76D11F6612D80AE53CD3E5702AEA0EEEACB6FD21861B68CEF12AB12C\ +AB6BF023D6F6F3771B237A9F68D5516EB85BC0907E947D702AEBF2FD72C196A087EB38AA\ +F77E04BEA1F6798F6EC164BEAFAD1BDD2955B8721AA6717505EAB952:\ +F544BFEBA760D22BBF72BABC88528618:869958C2FDFA5C52 + +3F20E497CC4C46C5C0B145DC2D1208627A07F0426608F4C240CB2C0E1B78858FA22280BE\ +9DB77EA591738F57ECBB4F242386CDA36E926FDA022400566C2AA3AA885B5AC734DE191B\ +61B66817B9A81D9F9FA9AA5F061E85B75DEED7A7C8E4C047923C6BB484747C0447381452\ +444FDE4658AD1FD3FA214798B4119D0133DA8EEB08E4104F84B4485047E9E48195F4408E\ +3473565036388A53FB9D657A7166DB7FE8F0978F01FC8DB66DFAFFD2E9B9FCFAD241E05F\ +856A512BB70DDF8CB32B34F00A06F7A5547BA92DD905DED80937E3A1478142A549A34B19\ +05A2C0183975E4DE684458DB2F80F39138ADA478D425453909AE585EFA7A91E0:\ +AEB26738E31E6C09771AED38B68F236CC9B3B7C512B16DAE7BB44F2F8ED5BB38FA0FAA8F\ +B4F8C9E3BF003CC4342BCEDB7F978F0383C7677622468E5A4C76F9A91CE4F3C2B26B9547\ +E6384EE50BCA15D22A7EFF7BC69E749AFDF6F0BE7DA7E60BA86C399C34C580E18E5FB35B\ +2D52ABD64A31F508711C5AD753FCC47D38933C581AB33C6F57E90090C7824A345046492A\ +6A94293040ADF91673D8FF6FB1B6C989D0C0A962931504ED2E1E056FAE8EADE632D27B39\ +8D893F2D3B420AAAFCAE4EA0688AB45335BE5E8D5E1A7D70A4C6EF1EDA6BE64AA0CDE393\ +9230E8B027B400CBA2615525C0377E22D5DB9EF150C316680E545B28D5AB02BD:\ +CD3603440E0D4ABFB32196ABAEA29DBD:47D173BB5D14232E + +9FF2357073EA8FEB5696460CA5570F82A65C9C8B23CBBDB54161EDF09BBB952A57F9E02A\ +0E60B53B9B29E47F64982A9D3AAF92CECA9B1B4F899C37EC998679E1C6E608FFE780EC78\ +0517AE6EAFE48474BBDBC2F59FE732779AA27380BD7B003F1D9D9977DA835C52A6D67429\ +14276C92689190A1DCE67F31A165A08053063F08C01A5C25B5666540F0802C7F79E64DA6\ +A2E8EE51888918CFA3C5437891E1F7186ACD7B48CC2B7C6E961C95A10121D4B2F20D737F\ +74FE62D4401ABE8EE6EF748D646B02B117885D6F9F7BA65A01307454094C66AF68D25740\ +EE9F45D7B9E12D9FBE44C13D98BBB59FFBBDE75E4E217F9BF794968A4B55F2B16DF6DD40:\ +30E20775061AC476109DEBEEC9CA69882E3F6FF8D05B913CE1ACCCBFADEA87B15AEAB81A\ +8414EEFC3938D0149A0DEBC42E1B3E4CD4D6FA0CA171F7CA194A5F57BC2BA3221E43DE68\ +A269714F5BEDF0F12FA33C456F839D30C4A9C7667273350CAE1E25BF98CDE73BC10FC5B2\ +02F88C7477B2973A077C567DE8408C3FDE4EA6722056D7AA0AABA3E332D53B686423ECC8\ +D8C69524D3E94AE42FE6C70CDFE611C7DA0E300BD81FED416CC0952F008A9F4CC6795D85\ +DD0732228628A8A3266782BFD7E041D6D135C329BF7C02F209EA97C288C613049ADAA270\ +2F654FB81166C23F2EA91FB969679917CDCF22CD878AAFE6E2CD8BCA63468AB745762E7D:\ +7ECC2FA94DB28B0C4CD002EA020B6111:00519E7C6392488A + +7E508A73B21580529EF3C160A981240BA4A83989EC072F7F8296DC7DA3B9F785D11FA67D\ +A1843A31BEEDD09919738D6E98AC7F37402FA60968E0EA3890CD0A0238B31AE3A26EF28B\ +AE750FF2451D98D8B405FEC83672C3A531CDEE25AE5566EA23C51CE747CB44092B82AB89\ +D0C3D0731DE92D1C862E50DA27A7024338FD62311DBB7BD2029713263EE16F9FF37EACE7\ +1EE5F25AD185A9E0327173F4287A93BAF814ADAF5AF869F2436BAAD8D8D3EA4908A816FA\ +DEE43AAC1B7E408BC049D2383F91D25D4CFC3537784E0071B5BB1614CE40C8E1EB9FCEF2\ +99C8C10DF96597B10BFF0606CA3CDD6AB72BBF8D4341222E36675360FA3193A0E275C955\ +90056585:\ +A5B2EC64C27DDC68D99C9F82F0833898B11B2355DF8F1CAFA49C4B3D67327A2367AED1C8\ +330F5A700C788529F78AC260E0DB5231DF15E01BB616566CF4E3A64F1F42B503E4240386\ +7EA24A5DBB80E5B6403BAF272BB480E0B39C77E4D092FB8ED54360912930F36B91C94F39\ +689F6571D948D9660CE319E1D72EECC0AF93072417F4A65F0F1823581B9DCF874094E327\ +41BBA233F5A998C1CAEEE53C331BA9F9D437DDBA066160137AC5E7D006DE9EF709B1D033\ +145CE09F1FDDE0C5B278201665BB835726314E1B76E8DE23E4FBE36C22F5D7009E6B7DB7\ +F151DB23CD520666101F7D3F699016CDC3F286402EBAE4F59ABCCC3A86502112935EA87E\ +1A993F6C:\ +0C8D98BEA46840B22546EE369F77CFFB:4FD1822D02B9C1A3 + +[XTEA/ECB/NoPadding] +E197D59E064818B7C8AD72C29E227E09:\ +04CD161E422154E5BCA5249582B9D4C0:\ +DD0C8719A8DA117DD9D1DAA189E65654 + +AE53AA320088B4042EAAEE3649FE6E36445696F01CA40D3C:\ +A3B303C42178F97F719449529D51511491B41EB70E6101C6:\ +D8C8ACF6B4B68A837639320798994979 + +655A6B1D6970ABA078819E5AE1D08471A0E01E0A5C64E612504F4BD9BE4A8AE8:\ +7DB966E1A2B7C0E8EAA9D308EF89652A5857461D100DD0CEF9C6FE7BB4DFE33A:\ +24059EA6D8A9F0CA678ED6680362596F + +F3B1BB81C053DB02A8515885CA6DF124AB04927D2AAF6F0032BF17B4B437E1F2C7D82F89\ +BAD898DF:\ +215D5ABF53C4AA0D7571A0D9D05C3B6D33D65BF35EFFA4778FF59DEE90900ACDD4FC6645\ +368A294F:\ +2434D48F17E0A7D91F255FCE60F3D6EA + +06F0A1AD9F9EAA665044D0A2EFA10ABC30F7FBA3FC47C6AE1947B7E9B47733547E5C843D\ +AC59D09393835061D834971E:\ +066309B116A6692F279F2526FD284E75479BF7FB5F63096AD7108CFB0DB39062A2627594\ +F098F0BF5A3B4C67CF29E993:\ +18C1E1EB3925EEC61559DB74EC99491B + +2FA1106E95056E070352666F059A72DF6CC949BB3161D5FFD8FE46451444D096BBD606B0\ +BD443189AF001E5BBBA134DB1FEA7AE9B4587438:\ +1DF05B34A733F83B7DA1F194507904CDA99C374174AAB472CC598E06960263BD9DD0EFA2\ +F4C14CC8AF4039A55EC00125766D25FBB7139081:\ +5258617DB39A2968B1EB02565A2BDD1D + +E6ABE28FD1E9392CFC65978D586D31D344140673E345D6AA06C75E1C03E4E314831EB94A\ +BCAF6B23F2C34670A79500C6142EE722FD7E408D751DCB30E5C63F5D:\ +3EC6FE802F4EAA740DDF34EB79798F458049FE09190D12455EDD6129BAE85D22FF4E96AE\ +B59DB9413DC24D41730454F65C443C819265B4CDBFB87F5ADDE7F4EA:\ +C4A02982C1291093144C64DA1E7E3D67 + +213595590E62A55F241E3D4CFCA65C1BA23BF801ED05D25A8FD0A06A9846BE3C28B9BA45\ +A2B32BE80ED468E007EB6EFF0EECDA4460A700977B84464631B642135BAB8519248CA0E0:\ +5A6D52C19193A6C002D58C15BD2490CAA36550B684A726C33F1A12DFA2D4764FB75EA336\ +823833637765F37547103691B852FAB81BBD74EF6C20BB885AC42946998E74D2B8C2BB75:\ +58B61987700468A366178595E20A365A + +7DE080A1683521CEAF78AB4C3160D326A07FF4C6F446A94FEADFC0BC8464EB781D743694\ +734C5938F7D2DE4822EFFF34A82EF0C2E11F92CF1E0B2989786FA990DA3AAEC7FC647675\ +024BDB47F20C67A7:\ +1A5002651E1686F56A6BFDD8DC40DA9DCAE7E4773237720BAC8962DC2FEBCAAD885C4A62\ +F13476B303B2700150F5CBA1CA976A753E6971095F175E8BA2D97E1F1C18FEBB0F8658DC\ +E957E65DA18D38D8:\ +75E691CF7E511D4B1A114C0E80BC7C7E + +739D59F39F57C04D1450926AD161AE7CF1522C4929CB299C2EE03842E3DA7AFD54AF4DEF\ +19867E278678222C85D8901526E62A008D449478FE4249173B6E80980B9F91D09F7F5CA8\ +A174EC73A57AA878E74F0315B6F3E15C:\ +59E210F2DF601ECB05F4FBAED1077A9AE1B783526DABCB881881BCD103658E03FD6C1D12\ +2508DD039470226BA0AA50AA087D40732D77D137DD2CC96824E24C44BA8955D250297C02\ +E3D444F4F1E78F5A02C50C7314CE356C:\ +5161285DC54A3D9ECB691C0CDF987D33 + +3A483364A30C28F9B932A11152D741304802030C60453D1E9433823A21F033DF5A6FB43F\ +E9CCB423946DD363F9EEA9F0E60898652E8E4C4B6AB6410B468861CDCE22B3043BBF7252\ +0232EB34D1685274A3FDCBFD9753DAD0AE467CF7EE661145:\ +11AB2B4CC8CC30311EE2B979C6AF90C5EDF073CA2E483C2F0207E8E95AACC55F0120C9B0\ +DC689A2B645EA1560FEBF3D027F0F24E551205091D04A72657209E814A9DAF3457ED9653\ +9FC1CC8937D76E2EB4854313E2C067F86EF889757E014B35:\ +19B8DF4B8C9BEBE46AE4F71FDB4EF5D4 + +A9E72827F67035507B5F0747149A73AC2763000470087FD6F8F165FCB872AE7BA58CF568\ +E1D70D28891881F0464207E5FF67CD2A707B71286DA7635085B3B68F9228A646A186C8D0\ +9D3E31B56562ACABD0D5AA32F608C54086642AEBB72767643C90B7DC02FF772F:\ +5AC440B8C9AF2D5843B125711F519D34DACF4D86CDBC856933C96D5B3CEA980E9DEC2F0E\ +2BF6E8EEF38214D59B5562324C009953DCCC4ED2D6C6B55211AC5E0EDC7C8AD3F8760823\ +D55365D84525E09DD3145DB6D700D9BAA4A92F38EAAD8CE33000A0ED72A1FEAF:\ +3D29E84526A1D60D177C03632DBF1E96 + +D24A21AB1ECBCF2EF83A1FCBC1032EED930FE269AFF8EDCFEE26FB1A2DA9D063EAE522E8\ +41024B7FDEDCDD6BAA1126834C996B9FD09654901FA8830C64AB1F5CA3BE896D5E60BE29\ +D08C9E0A4F07956551E618F1FBF46DC8255A4E2F4DC8DE5729CCBB39FAECEA0A4C45F53F\ +CF5C3973:\ +2A2A34F1EB3F99FAFADAE4A68CC85799D9EB7B1F0277E71D56FBC395E3A93980B670D36B\ +87153B90B8154EA962C39A049088665EBFE6D43A5E9A04A93F4D683DD509E27BD3AC659E\ +5AEEE8B62EC3037C425EFEC0E726E8E572017940725A794E58817914308832AB59644B03\ +D1155D33:\ +10E1FEA37BE818FD0CC1421E16A3151F + +9CF0C3E72880B2C3FEB787D84866DB80D4B4EFA60E3708CE6FAF0ECC29EDED0C8D9EB269\ +57F1DF63FD39EB11158DD089B9622D161AA83E0BB921067F77D6F4479B17FB9C9F30C4F5\ +6A86EEF38733C8D557053BD4978E41B965CF1F2025402836AC90935E9564BF23F5FC76F2\ +9DDBA491446695A82D54514C:\ +3A8E38AC17AD900742F711491153A7FB93C04F981CF75FB34FC9B28A2C24A81C60AC4585\ +DFE04FC026B6731A8C2404E65DE9FDAFDD32685A3863EC4CC77490F8E0D3ED234152FAEF\ +3C8E1BCE7E4BAFD1171141D5ACE23BB3E5EAB0F20D000371DEF9E831BF716B6AC5EC2313\ +F013766071F3AAD4492FD780:\ +80477A99D76ADDF3DEBEF9E8FF185DFD + +C1BB0B801F25223FCDF8CF13251877AA8472CA6924C0F51F1C968E981CFEF665F99EC57E\ +4C33C3B083D7DC62DC0096B062CBB6DDF4D39DC28843A74E81A5F9558FD9F5F74D3857BF\ +01A341BA443A2440C85CF069A757AA0E1ADD2B67860F3BEA805EAE1316BFD5638C312E96\ +614607B5BD816B55FA16C301B71212B5B1203F2B:\ +D481D95387B075DDB6771A669D3E11AC591A629B53405802F016E710D5E919E195A4553C\ +F83337ABBBD506131F363D2BB5A8D3B542AE8A99B4D4641C373BABFE737C14AC6612FE46\ +6D2A83C867F42D4004685B230D3FC1C23D3410D767353A5C523B0B36E0D35D9B3D9605AE\ +9C8402D0F7679A3573F3354E6BE0F2D173355B6B:\ +978393BF38701AE612953AE4C060B632 + +0C0627A330788002C9DCDFBBF23F46ECFF4CF793D93D934CC553A64ABAD1DEA3710F775C\ +71D54412BB3B6361B54C5E2DE7244CED9B546D146F20D8730FDD8AA155EAFFBEF34C70BE\ +1F6199F67D88186ED039E00BB88B7DD13F071AA4C309CF92C10DE3882674B5C5C5EDB457\ +F826C2D62724E1AD328CC09FB4113E083E4C4D31717FFA66914890CC:\ +5AAE35C53504B9DB9CBD7C00B01AF71772BE3E911DC6EBE45C1EBD331DD81CAAE710F963\ +7B2B22C12BD16B0D84F0B41A59BF169938475F56B57347362C7E6EF4F9ABAEC9F44C3BF1\ +1BC2D02DD0DB00A8DB780A1D1B399C11485EAAE96E1AF12EDF48B4CF6FCCD343F16CD056\ +5E843EB4FE1DFFC1EE2FA8E0F73839D6F6E131442154A4972F552DC4:\ +9A4972A00B5C1B22AA07DA8C1C8B8FF9 + +F2DF92A7AF36169DF9F2CE6DAAB0788284FEFC9D1C43619FAE6CB75576EE173DA697A01D\ +96835B357C89B737794D0E5B2C7F02F8E5DB968E2D000AFCFDF9B17BFC8383832A2CA177\ +CBE99385C9314F94977350C2D4B4AC6D37E0EC8F36E666C54011B2ABAD25CA922946A7B0\ +C9FB5AAF54D618BBFE59C1751404200BA90051B5E54F64C7045B72B01681FCC6E7763F8B:\ +F090795579AE3AFE49B96ECD3A8C01D449DA8AD81AEABAC135EB9CBB904647D5B1522B20\ +8F325C0597A2294CC1A10164551549B69E96F5AE72DDE9A4656AA533FBD7E98A6E66BE29\ +663176D5621CD21F29494D1CF6D784432B1524BA56BC3E67E9FB4378190268B4DE6BA74B\ +8B2B0E1EA52B75C45FCEA715B8A00B7D2456BCE2B45B192EDC10FE777FE53260F8E25397:\ +8EBCF7F6F9025BD94D2985A4D3982A84 + +EE4C225C44528549B4F609723FB33467DBF135FAAB3F6C82DD9E3383714F39EBB31FA595\ +850389D1BB1C1E9DDC3D1E0439F21B819B3D294B15EF81EA1E95C36E75D20B4C0D7C3765\ +E97E9A2B9E03B5F5D5705DBB35C241779E232B0781EF9A3F371D89E451DC68F6F7E0AC8A\ +EB7F8E41DEE6A0A86ED9195CCF12BDBD820243865FDD31B8D0F33418023E2089BF65A5C9\ +D20E03DD7D4C8287:\ +355BDD01480727A7496347973315434AFD0D75AC1AAF3869A461F78EF5E5923A7C4F749F\ +7929C497CDCA398F4CA868A860E0296A952BC115C07B38D5460753D134E8111C0C108136\ +154EBC7A386921F754D1F116F474C4B7DC8B5515ECA301E30D1D4661FF2814621C0CE1CE\ +812B317C94EE900FD23FC2D941504B345B5BCB4DF7CC3A01BD3D759E4A7C4C4FA893B6B2\ +30D21FEFFB69C0E4:\ +C2A7EAFAE3BAD26025FBC1EC1F3B1342 + +FC2B09E77FD6C0DFAFA0EBA6AA058D2357A620E4EFE70E52E8136B5294EBCF97E3DB642E\ +3062EDA1DD93DAF24E97FB14F41C53D38729105BB46DB59507B6152CBF7747537F9FC8A8\ +CDAB5028AEBB26FA8B5E020D7E1D110C159425ADA07B6E2526106DB5C1B4E2F62B5FFDD3\ +98EF3581EEA831FC686389C19E679B394A79D24AA34403BAB37A8B313F82878605E027EE\ +D34926D390BCFBB1E786153B0379C382:\ +F330598D81495B8AEFCBEF71B791A872B394E7A472E4E9E4D4C4DAABF7C2EDA0AF52CC16\ +2FF5001DF22EB012792A509C25566AD0BEBA50529F015CF3C4E6139C80373604EABA6F75\ +93AF87B31E300A3A2C5B9DC10EB36DE921BDF7E5569BFE8A4155F6F5F272846194E0178B\ +228E15DF6787AD158F0907205FA941D76BA4A4F2C121652806B463CC1DB8BDDE50776BBF\ +19577A25A66B4DC3230870963E53A137:\ +86014B66CAE76E61371F64A580B3A3F7 + +2642676CAE2461ADAADCE76CB12F9BE1A85DA497B5B6FA3FFFDA136E5ED6E53ABE52AA96\ +1D3D12EDA92644D9CCF6EE1C0023744BE75786CE57FCA3102D0E4AEFB3F6CF7E0FC1C74D\ +37DDC4CBF3CD59560DE06209006A55E8C463156B8F1D81C7C9FDC270A39FDBD67F53A196\ +73514569BD75BD747076C2CDBCF51C98995EDFE830CA8372279EA41819DC68ECA82B2476\ +53BA8EB10A8F909A762B74D9D46D7BB3E29C725C74504D0D:\ +20401A5F52C04821DB0609B9113ECE78977DB9A614CAEF283062D84985985C50090D64F5\ +BE66BB90E68D75801900FEBFFEA8BD5790337BB0ED215011E541AE1285FB3B305E05F4A2\ +4E2CD6D3A62EE76CA4DDDD2E371A67E36DEA94EA5C26CA1D1B322F249DAD9C5DE435D770\ +4B4F29A7D960EB9582316EC193C97BB5B64BBB2ADE27F250C2BFBDD48D660825EBE99E75\ +C0E4354E0E5B84338E6361A5C9C368F095D3630C3E9878AD:\ +372ADAC63D66E934514CB2E26B388F25 + +26BA6EF5054908E2CE4618CFABAF79F8D87DA4605B7F33EFA1C6AA0F039E138CCA821C75\ +F0B2D17E52932B25CDCDE78DA2BC77432786E865CB153E0A0C637E9691D08679075095EA\ +47DC18F40435B2DDD071D066F3B2B792FA528C0A64725F2B07981A2FD91F658C49B75317\ +FB963B2BB68430EC9FAAE98963A8EA85F62AD4F77E115D3FD979DB421A773F2454E6AF49\ +BD950550B126921E2FA581EEDB2387EA285D652DA362BBABE6F7D8454074B6C9:\ +9CD37096F29ED2C56C7D2842883A79D712F6AB9F5F08AED655CFECAA2F482FF470D74597\ +188C280E8FAA0B19B51B56A4A8B2B8E3ACE48927A61787341F5DC153621C14110710895E\ +4AD3886ACE7599919C985C70A8B9A7891FA43D1CDDB30726A2D5027D77386E5E8B80BD7C\ +BCBAA250269C250A8F2276E052A88997182528B947751DECC3E8555A8D4C6D6C223F7B6D\ +431AE2C7931DB88200DA4D987FA0ADDF0C0C8997B7224E06F9701BFAAB2E99CB:\ +B4BB2D7C1DCCF12BF555DFBFF33BFA09 + +C1EFE0B080811DBEAB17EB4C00E62F695BA71BB8E27006187F6F224F29D83820BEF01EF2\ +6D3CD5FF85CD5B005FF0DE9A8795B20F31E4D98A3BAE15B7BFB60FB8642D77C12E488652\ +A26B5E32116AA0F7177D1E3F46C31DFDF212683B08E84C0EE72A15466974FC5024F3A0FA\ +2061F53AAA86B3A29114D165C150D6FBBF0F07645C91CB5C9EFBCB292ACCF7159203BF83\ +A28FD040E92711854CDB4679A6D885FBADD29438BA11E9ECBA68F8BCD4433F7DCC6C263E\ +41C3E64D:\ +781D45863F3047C63BDB423712F166E4E5D018A6CD05B70E1131622E93BD6E0CB56735B5\ +335001B9B971A671475DF0EDBEC0FAB32DDFD422504A941860C223D86B77EE2A4F7CBC44\ +34738CF7F59059EFC0CFE4693FA9BD553B5EF3C1F311FDB66C8B4117620126768A742278\ +74D9BC89FECA06CEBCEE39528378B1B5915543453E667860D94C0406543B341175650D86\ +5D245225B0964BE723516490D8F908DA7B73A72C790A5B6CD6B980D0FF8DEFE9BE085916\ +3D3527D5:\ +FB8C5F864EAD033E0F3D427E76B5C9F5 + +B863168DAF023E33D00F90F5BD076FA62F3BFADC93F0A1EE0E1466DC87507BE3E0420F88\ +4D40511F5C1A6DC912E70F33EC90D52E2F98FBE89EF076E3A95CF011F6ABA8A946B409C1\ +96ED86094597D35C548EF84ACAD0CB3E292CFC4D43183F4D97C43BFC5445A5DDF396159F\ +9662D0D844391075E5A209A00CFD49AA86519F7C3DE285D9DD02F3924D0836C725AA0669\ +F3B98C4B42AC893B90F55D4F07B83CAD7F693BF49D72423A369E7FC563D44229CBFB5F7A\ +25EEBB50DBDCA0852851D417:\ +3F22A08DF104CB891887000C0B975296A0A736B7D074739DBB7B16100EC96EA30F84438E\ +3C9B6F38063C2C4FD8B39262D828F000B8176D6793F8537598DA976A29228966AF45F698\ +BE394FD0FBFED864BB1B81BCEF8D9FED2BC7FBECEFC31D319D6C54648C9C0ADBB83B18A5\ +6E8C1D72DB37FD24EABA87F6C9767E3B3FA4566DA71D03539EB8E558390EFB8B1839AFEB\ +E11FCD2F81774674228FB965D4A78164E57F5348DB47E06C0D2507B9738F3750D1780D49\ +E485B9CF89A7C716F9A628AF:\ +4ABBB43F2BF9C69B02AED5D4D82310F2 + +FB669C4A5B01B8808E3A7A08E47D2ECE63202C4F896402163D88BDE3FA02A0C7EA924B80\ +8AC430A3A157B09FDA1991A18DE25F842E2DD3A221AD2804660791AE592E60D9991C59D6\ +D0E50CA49F1F4FF5AABA0C81DA2C36EC169B420745357B82201009C2E2EF15853C65647F\ +C93B587E25415AAABB8AAA7B441F8E1616A1DDBA24C83935C5A4755C19719837AC1EFC72\ +75B37E264B1AF004513D53BC94BFF7D6763AB8AEA592FFCE8725BF2CC06C711AA2691475\ +CDCDB82A28ABFBB1D166A20D3563B66060699F16:\ +EF73A9BB5596BC30BAF024316E5085A71F83CA9C8BBEBA4C0F5EACE57BD0F19A9688590B\ +4F255E048E90EE2F8316885ABBC82BD6F15FD6AD56C3C58D5FE6BF3BBBC6795E4E9D424E\ +B570CA5775B39EF117F4D0337F88E6B3096F0206F89D01F1EEB39A388F42C44CB03AD06A\ +6A4E914D545499852E2EC5F1F35556515FC7D04E884D48D92BB1ED179C485EE5E5B136F8\ +1BEDF14ABB843AC9292B80440FDB5CDD50EB573C744AF2444BDFFFD785FE3535F698F446\ +B533FECEFC1ADF7752916B2B77C68F1AD08A77B5:\ +8C366409428A56AD49CF09F5C790325F + +379AC957E6721F2C33CFA9C8E8FAA85B3AE28E346E99FAFE06C5F2497724D800C332A3DE\ +25424523CBDEBB0EA95AA31C88B8A00ED3CF0E90B42BC1CF690618CC15796E1966AA5706\ +7D5B7E172A1F818C1C7EAF58C27E6EB3F647879E9785FC8362210C8E8C458A60AF1CFDBE\ +F698869E3347645C6D9AE7407F8DC7A1F84B20C1CEB17E33320F9BECC4B3E8E450BE9F59\ +56F74CF33F764526F097DFCB63C57C9798F791B471C494062BB6675C374EA7273E69C12B\ +5349172AEED9C66AF0380490B74F2293AA22DA87976580994A5109B5:\ +7AE8556DD6A8EE6E86499658479AE39CC400452F06071044CD165FF5C2B85FD59DE4BFEC\ +7FBFE20F578C1E21A53BC896D3FE5D77C7F908FA96A68FADA439645F621ACDDD9E2F351F\ +1E4D87BE5BCA2D6C93584DC331DD623925B630EC01C296F64F71DF0DD92232C7B0A0DB82\ +1B1761A442CA73EC3FCBAB386B0FFA35754ED91B113D51CD9239DF73ED46BBE1485075BA\ +AAFAC363F541870AA96EE7F21C4ECDBC0DA9F309B2CAB1C77D6220B2BC9EF5F2319607D7\ +C3D32C9F007C21CCA676872818085C971FFB778138C5398EE372DEC9:\ +0D852CA9C6CB0FA6A95F2B0D414A6F19 + +84B35BBFE1FFE781B931EEA1556DBA23D38673BB229EDBAAEA95A93736104DF3805D4968\ +95F105FC5433F698CAC70526A74EB67935788C35D87E6ACB63A285999CB981173BA6EB6F\ +8402F89D4D2DBF0A5DE904D5BDFC4864C6E48B906090DC418E9A91BDA8BE63E3CB341B57\ +0EBA6C5095A478C0FF43C062E12FB180D0B74DA39F7B562FFE9F652B3FF4356BA024777A\ +C34D7F84C45FEA5EC21BBAB205C6FF43EC92782BEEFD471DD8703FBD5DE167A829443F5F\ +1EE398475A40049C2AB577B5A6BF2581420F38D22F46142B59C92ED80F44A22A49644843:\ +17B0379B31BE60CD613289C2176135F971DDAAC953B76C8B48BA9FFCA0A040EF00E97A32\ +0FD19C9D4CB269AC205DCEDA98DB7390992FA4FC567DE5A39ACF08DACE83858E03E3BDE0\ +7B75AB74CF4D90DA3FF2B95476F9A81853BFFEBD91450E71E4D5BB5291BEA641F8773611\ +12D65E7578390A71CA8778CFACD4D25F71C90D289AD29045358D1DC8E14983E75CCA03F1\ +2521969916432CB967202086B62B33AFE1FA5B5A68BD4BF19888922F814577ED0E4F09C5\ +0D884A7DAE5B08B2AABFA8FA159BEA131841CB0F3B63F826E36682208F78839D9E84D917:\ +C071C64B7DBA548A42CF9656521425FB + +AC1211AABCB5E081D8C95FDD138A42FD6F1D808E37077D65D8FEAC80791E5D169A32B2F3\ +33CED7B84CFA383B430BD7611726230664C2471C0413CE30006872B0707DBDA38F9640D5\ +E376D050DDD5526A3313AD1247B6CE98F1484D9FF0169B7190F8D4CBE10BC03234E3CA25\ +81EEB98DC5969E2EB57A4C5A10DD5B5619D80D5A9B9C3595EAD7E0B5B622A5A2F685D70C\ +D687BEA1876C74A29DE026C1F8F673D66F1171B1633A05393A9896705A8E504BC474083D\ +B285BF8DD893D3D699505345EB97985948DA52A17AEABF279CC28E9793D360E8D707D5C3\ +6C0047BDC6ABE83E:\ +40BF0E1D3B5D92417849BBAE059D7EA6F22D409F5563957BAD0A4398F963AC823AE33A6F\ +6E908AC004E94A5AB9E3E7C4184C94FC90EBFAC6CC70C60FE939453507BB65913FC9A977\ +21A730880EFE22439DF0C516009A06FAE30F6CED63D9CEB707C331D0EDC2945EE3561EDA\ +E176E525E66EEF01E4FE4880F8F7D79A32E45CF71300A262A5F78079C20D7A9EB543D226\ +9579EC077A33EBCFB9289EB85C979951923ED96ADAA2984D6DEB1F5B3FA9CDD859EF877B\ +7594E84B99E3A9D2C8B8F984428D18A1B59EBFB851CB8EF0B4719725CF07D73E580C18B5\ +37BE3AFB34186668:\ +BC12C0EA9A1D8C2F0CA4F4683EFB8E38 + +2D2E50EFC0C6378E1D6BF584C498600F883CB10A49E27325E20A018B0BB3F192C7462F1C\ +F76636CB86F3CE38DBE3A70502A7A6F72EEFB76990773407DA628C11FBEC2E8478EF2F98\ +F0BEDB6733F695CF0158B8CF5AF6097F84116CDF8B973F3B0A6BC863B12EFCEDF0AD18F4\ +755974E9A05E554654115EA2B309DC37D41B7C1C6686C6470A7A528BFD2E8ECA7E28657A\ +BB5BC34532C38365FA1BA9DAA3CEBC85A9F30195E6D4EB52EF8CD243AE7DB1D082501FCA\ +2A93A4A81C4E1DEF5F4E0625BB088D0B2F4C31DC26561179DC3B46DFCACE0E82CA9A0505\ +8E2118194F6021CFDBE0D8C1D7B6D41B:\ +A6A0348A6F587D6664381AE45F8A0BC69C51F7BF6C26755452CDDB4F1F101EA2224F61BC\ +DBA8E97067DA55F4BF59A5D7CF12ABCF4DF18B92E4B6921569051F5E70F25698FE0D6C19\ +B891B48A3E03EBD7FE4A79A250A8B5FE6662D4430725AC447B55BBDAFB259B323872B4EF\ +BB452FB968E979006EA49A789F4C3743DBC1306AFBF5A4B1F421C99A3AA07A2E98A47B4D\ +AF2204CECB2AA86FB9AB60125AD0CD94C799CF3EBEC65C6F4F2B864C11F513CEA9D6280C\ +DF16B1F0E1F943A444786E1DCB1851681572ACA9571699B82CE9E5275E6999A1EEB599CC\ +8A0583D11D47938324E95B67407A0D68:\ +A114856E299B436E09F437C57B15109B + +AFC793265B90D53B647275124998999B3D8C91440541DB7E8CB0E8837AEB4653FC35361B\ +55D659148D9F25E3C109B1BB92C037397DA8F91CD5AF0B6EDE7667BFCF1DDCEE76AE83F1\ +67D937EB67005D48A9503315476A43A45001F621444C562563DE6901E969F6662249A6BD\ +AB7A638405EA3AC01304FD2DB772CC7AC122CD3D65B749A3F31704910950B642C8E5654D\ +C10B07C614C65A07BDE2AB52196999066284CF0F6EB66CD1A62C29B683A436C5BBC15704\ +688BAB92972421903D53F2072F7B8D53B02B70F63E7A7503207360A4872E04CBADBFEB32\ +1BCDDEA5E89419FEDED04000065DF73BE58A79AB5BDF885E:\ +6CAE06C13E54BB2375E3D3C741E9C61D3813AB63CB157E54FAFD28E9A4D935E57D74032E\ +5E669844D277F211B480F0E54E4F0B09C2242FE1D5EEFF32E1313759A47E7450B55E09C4\ +37D1EF3F60A0572134C2D9B5258414BA5D84774D65FE545F1B80E7FC06BD7669D05AFAA2\ +271AEE74F8E0C247070CBA2FFCA62B6CE5BFB0B6E75055F099939AC44FEC6E9A3615FD57\ +B3723119FF14C927BA06DFFA36E91744E035AE7A9F21625D74BB62C41802782201D1043E\ +5B9AE266997FABBB42ED800EA1E2F2A4E78C265E3CBAA9979ED89A8FC6C9F16BC6802A5E\ +7D2D819A7D8357B9C40B5BCC50726EBA3DD0791E11489771:\ +C722C9F2A15369264DB7F54FEB0207B8 + +936C9695CF82D4241CAEDA1E8C80DA52CA4837BBDD2158E2CCDAA99EFEC6F1FA29D6ADDD\ +6FE3A660F50FC6C2AE456BF742081FB471A317707C523638AA27DD85621CDED72631C469\ +0A857512265A11C283193BE33BBA6E77EACD56E9DF9541BDC3567814E98F0E6D57D9B254\ +40FB7AB62AD9375B2A96F60C4E4B57AD02F62EAA06793D0C5761369447B9A0621EC2F9AF\ +BE8F52E8720CCF67E4A1BC7285463E8DEAADC248CD8207739F04FD13F72E0A7A0CDDD5EA\ +0B7111582A389C21F499BB4349E8BDFAB0925E4C299773A9A546913D37B7951C9052EE94\ +55391880A77CC66F133FB8AF5CBDDB2433F3F9D52F94A15D8A9143D0729F6D60:\ +8144D92331D338C920C0BA0C6B32C6EE28BBCE148F6B56B5D2A12D029734A41B8B4071E4\ +A7601A88E8CEB031DDD38E4588CCAA900E8E23AA1C3D4AAD39FB75B90A8C47ABE3641FC6\ +B04EA1E74FD4B4B9E72310F79D25509B3DCA63BEB093A08F7149A23E0D548DD5C20449C9\ +0FB41C88CBB6D1D51D35DE46D4112090926A7948563487E34E7507CCBA9825BB48EA8709\ +239CB49CBC0FC09447570E1FDE99E1316BC24A5CD38E53F613152BA9BAFEB065AE30CD73\ +DADEF90E4E907C0E55EA0488B9CDD20926B3893D8429E4C9FCEA17087B6933064976F250\ +3ACD2D8D0DF4CF6F10BFEC0C914B0C46E6FF575464FCEB1EDC01AFBE446F77AC:\ +BEF7E425E917D067300D40D19AE12ADE + +23D35E037CBBA0A76A46DD433B547E17B54A81782A51D13829BA301250ECBEB0EB598F76\ +BE470D8411E7E58516873B4C9BB87E4B41C4DA3BB941C3F8A9EEFAA507D30948692ADD5E\ +53AF8EF3CE42D6944D8E2994F45F4090B8934BCB09B94B3BF04726F42B00ECF9D9893BAA\ +ABFAF712E022F82317CFEC8AAEB7242BAADEF7526833C2EA481816856BD423CC652CC043\ +01C7212BBE69F251BEBFCACAF0F12A19F99EC4A88E4381403B24322133373ABE881C0F97\ +D706EE4CBF3F5F7E69B8624F50270E508ED0487B0B8116BE1AF904C23B4F704BCB8AF92B\ +118A912B5CD0D759C3F73A6331E1337B693B7EA65A017CB62C51A4E4AC7C6AB9530DE747\ +FFCEF27C:\ +D968A79959F5DCB6486FE846504AC0E8753E56410795AB9637BA84EDD9AFD692DA253ACF\ +DE1FCEF40280D30BAD93AF2386B755835AD1CB18D472DAF37D7C69109DE9898E09C69DD8\ +D5DAD6D6640246B28F905FC0B1329D44E9AD2DD4D5D467862AE364CE7A81D5433B00CAF1\ +1B9A1D7D54910CB2B01888348ED423A2BB40CE0CC23210CE10CB9B123AAA8F41A3B25114\ +398160C0E9241CEF67F52CC419AD31E5E04C4CE91716ED99702AE69E7A1D501C47A53F81\ +E611827C7694E9B4B9446F263FF1170F4CD70B432EFEF97F0916CC6BA81A8E11EC996526\ +E9202F6910FE8A427CD0BC8C7BFA23D0DCE30FDD6C2F36B582A3C9B698BC5CC6CEB3F951\ +B26D586B:\ +19796BDCABF22920277106075D0E0EB0 + +[XTEA/CTR-BE] +ABA78D16A7A85065A61F31B9C9CD4053444BA2A36C80E97C4C7BD0956676FA39:\ +4B33050781F6003A1A4CAD8B188DA93FAB60C28BBC1E5D822CF7551986E2A5C2:\ +EC1147D3A4CB70A20AA8664E88E60985:7A38520947DD623F + +14E75459D23667074E7A7373034443BB4B2C7CBF90EA1A18D59A93598090D92CAB4F8F15:\ +7C2E05A9570504B7751E4614FECEC7F7449FA1B25895C4435A29AD9DA8AB41A8CF06048A:\ +2FEBE8549A5DDDA945398955CBD4D3E9:2A95AD603EC4B59D + +9388E427E80A52FE5EB761560A2494526DDD7B4729FAD683E6C8B57FB46782B9D016AA0D\ +DFC9C313:\ +8020D203BE99C6EA448C64EC4CFC2F02AA220CC6194EAF81D938467E8BB69200B2F67AB6\ +D6CFF596:\ +62F04E49D6CC94750FA5CFC871DBDCCD:25723E1410D2EABC + +AE15285DF8745CF588C3D075C545591CE8C87E0840CD8EDC9336ED08E42D2A4A6BA0B7D6\ +045AAB25645208BB:\ +82777E8462001C6BE7990AD149ED8AA462CEF8FAA7F3377CDDF07BC89F0A2EB39439756C\ +31D21E932FEB672A:\ +F7E815767C7D7542BD8F0DB41C8C0E95:8FE94927EEB3ED8F + +94E0F6198EC8C7C7DF35262ED38CDFF2D5BC48A1FCA450D250345996EB01BFF3965F221A\ +F4EC43D8CB7FB89ACEB01B1A:\ +8468BE0862149C3CA03983C7AFFF1D61C33FAD83477714CC51D40C6F1F045530E9651757\ +DFFA70BB1C4780D6F44A0E9C:\ +B64DCBD21A7CB07620DEE39C74BD598F:74DFAD2D6C7375BB + +FDEBCC1AC9107EDAF4AF10F34B6E1C8EE15797901F35840504754EAB53BE680F30BDD571\ +E9B50289987C6292BF2CA838D932DE34:\ +76F9EC52A2E6C5EB209E7CFB4BD40EA0CAB974068A0CB4C3490349D3024CDC522D11FED4\ +D91D32223FFA8916B39D458999FFF43D:\ +728984B99C7E92CDEB49DE0B3FE42AA8:888F01082B9D2103 + +9B0E0711E375D8EA9735F98F38C58E9184E66EE71DD12B9E14F80095FFE53C6461A3A362\ +650D150C2FBB6F84DCB0789D6E7CF63D8DA9CD6F:\ +EC83CD5B6D2DD5B438CCFDE65580F1A45053D01E15370119219B39C124A4D99F8EFA44F5\ +001BE7F18C7E0033CB1411AAB97E104196434346:\ +E55ED01805B70BA13D785D8D859F15D8:5C8907CD33AFF98B + +22E53F89A5E86CD4A874D5CF372E51362E8F71728FD855730CC87BE1F57EF26577689C1F\ +5390C158B6E1ACDBFF1B5BA5D90D6B4F0C2D484D9F0F513E:\ +33F1FC8F0B7B13EA9F2676597870D55E285F7692B5F89CFCAC80127E5E85D1D3C5D624E2\ +2A4C36066F7EB9AF665AA1C7799863FF3F5EFA3FF027CB9D:\ +1D22726357C301EDA933D7910D3135B4:E046855FFD91DF19 + +C1EAE81700F699ABD728F04E671BC2623B70BE954A9CEF23CE43D492197DC55713406212\ +CF1E322EBEAE57601F2B717AEF4A3DD4EFEC18BD9FA55B226EC129DC:\ +25226E84529A261AF51E429148A35B389A88809B75D983720084586AD0A02F2851CD92A7\ +2372FAE97A65539219EA224A9B1BC6C7E8A0586CA4ED37C3D452DA4D:\ +065EC565D8BC713866CFF86B0ABC2BB1:27100BF3F22105DA + +325748DA5C629AFC738D34BF32C84DEB40543C276A3A2C13C6A4BF23B885B6AC348D2746\ +7BA3714BE4FB1B764B81FAD7EE2D062277B4EC428F0A6E6CADAF5EA55860F8AE:\ +A0FD6A60A1B8A729CC52D41FBDB2E5E7896EE8C9944E6E63CD1A769BF278AE2E8CF48115\ +ADEA864B00DC65B950C68D09079CD81D35459F5F483F9040FC38AD50778B4217:\ +6AA995999C4EA6C83070988AC0A795F7:01B5B1C6E92BBEE6 + +23019A5A7C61262EA124DAB215A517423781B9C1BE56B63E794BE6836026F7CD55531BFC\ +08665896FCC7CCDFDCEA09207A8785C8DCE932A00A5D105A2D6682A32604D1292207F195:\ +47CDB6D6BC25AEBAD70E99524CB0EBCDEB48E0531A35E505FFDA421A1F27ADD6BB9ADC57\ +C3525B989C0C1DCE37577877CE328E6D317D0655DFA80AA8B62273C7AE8DDDE05EECD178:\ +E6D35BBAC75EFAB74AB954C8C2D0D1C7:6582E6C1B4A47B2E + +9F8B703434DA473871B05A0D83EC424FFBB0DA17224C95D33178FD28641C1ADE87559E7D\ +ACD11F819CAED832B095F6F804FF63D4E239D620B8E6CE8DF1799D028926A3FFE28BF433\ +664B166A:\ +8E1F3C026E4885E3693FEEFAD56DB8A898269D61CC92CBFA0DE1DA833586619AE9D0B98E\ +54028A2AED24BF2878B1894F4BFE090CF0A7F2627106DC0700F43D31914586DD1A1CD7A1\ +A7F5D82A:\ +3145D3926C22A5AB4BBDCC163CE93E0B:CB8BEA9267176935 + +4592FFC1D25A2ADCC9FD5DE77DB143AA6E17934FF882E2F8E2BF0D8BFE6DFE10AA33D124\ +199BFAE8D3C2BC2B4B9EB37FC6289C0ED2A6CDDE407F78C035CAAB36653FF686FAC37E51\ +76B3A821E21CF7B1:\ +ADE67B169947C994E246676FB301C44204D8817BC3291DE6F35552E1E8BEFA5763F1C605\ +E2CA7442847030793EF1CD830F7103ECC9928FC98EE4B346872ADADF439464BA40CA0D78\ +63C4C9946E723E71:\ +353358DD5493234F6BE6E3AA3AA4D393:A17467FA740E2541 + +E3100B239057B16CE51A754047F20D6537DE016ADA61056761C1D9DF3939AC8C0AB155B4\ +2C9C3BCFF3B63BDADD21954C328B4CCA4F1EA6A57EA8B7A99BFCE72E57CA2C87C4ADF0C8\ +44CB76A4B8DA35BD0A3952AA:\ +AEBEC1E382AD5129278CB4C5A67EF92E64BAE93C1F4266FBD40AEEE0E28D5048E81B0CDD\ +2EB7851B7A3CA43BFAB751C54217DE5315D9EBCF94238FBA5A8114C28F1AF6B9110DBC84\ +EF13F621B8690AD7480E9E90:\ +C313724761DEC636790E38D93F299530:90C5A696C66726F2 + +6FEEE7F77DAE629397B0EEBCE6A4E7CD4FCB4F14EBC408A6798475F3EE5C560F0C38FB0F\ +9D2334E85B75C36632EB4C9ECF80F02B47EC1D589720C104B111197E5CCE4D08441FD98B\ +9D67E108BD5AE4313B5725F7B86BA4E6:\ +F73ED0FABED7812409A04F100F1523DA22E013055537803A3F6B2ABE9479A199B2DF80F3\ +F379640228C47C0475A68A86A455B4E53D2CC078A9EBB04F37764714EE9F0202BF15C393\ +CE87A6E339CD0EA52DA997091383D151:\ +3ED02192D605AB5AAE56CC630BE39141:09808B88D15118CD + +CC1B18F695290A169D5DAF220622250E4C3383C871CED8648365EC2DEC9A14D5A522441B\ +35B8AAA51FD6D06EF8E5C8F6A12F8EF068882B826E1B97844F0F088C1214DD1769E6F1B3\ +29CC62FEAE91D1AE9CA752AF80A966AFF9495BD6:\ +D86A1A79CE209972F3F5DCAB0389DBA578CB0EA6FF657E889CF6CF7C30C746131E71927A\ +3CB2DA42A823A19E176510CEFD9AEC30D7F648097AAB847840ED396FDFE4CD1EE0C131C7\ +63C17F551457E5D0D933EC1CD30ADABE4E69298F:\ +E53B03BD00F9E5817BBE38EB1760F950:D559750E3DC7CC19 + +D150BC8369DC06BA57F7CC241766549A52F2D49D7AAF9CF7D6BE0334FAE2327FCC76104D\ +E5EDF782E32B8CCF92669B62B25FC619DDAB77BF9AEBB2D175530AE97B56BE01065B9532\ +4EAF86AFDDED0C93DE01F139E6B0302DE8F59954F0B20793:\ +16DCB3F6A247FCECB4B5C7790796166540892230E00AACEF9EACE255ADF579F6BBAB2F2C\ +92E8389EC54A6F039963E980550B073C0CEC4FE554B2A23C69776D35AFCD128559104141\ +5CC9A15BD1A4A89AF43F702B06F1807FEA53490B80686A52:\ +48E7EF6FED168BCEC4069E3E622530BF:7C8A47B36E7EC263 + +1B1508A165845B4EA7692CD8BE5A38B42AB114B9A63E3243D3DC1AEA8D279E2A12BFFED8\ +88B7E4702CD51CE577E04B9E401C1D6ADAC4222FB87A5BC81CA331DE77BE79D3C9287839\ +8752DC9678D5ED422E40B469515A64D1E561DEC0D3599CBB88AD71FB:\ +AD25FC4AACEB3BF13B5620DD0437C0E5EC62869F5C0296C7A0666CFE974603D9509E2980\ +4075560D1674EC8DF26BB7FD8F9438731927DF583D8DEFC45E960F0F03CC71539E56F6F3\ +3FF324F265D4E3596F97630FEA0521C29210830BD5514E8DC390573D:\ +F931CF1396F15FE1FBED7A230961C729:5DC1DA62482AA6EC + +969875002E0CF955F29EC9651D8AC98B667A8700E96EAFB42AFEC3EFFC9A219B614BCBF0\ +C32028EA2ADBDDA5D0E3444E1658C7E0CE20362E00EA73B2428027FCA2061CF6B492DECC\ +FCBF06E519D05BCA2282342DED05B0CF2E1E25639F58DCD220922B690C5B5E23:\ +4A1A307B23136A6C15065ABE453209D1B87413260BE453F7231629F99709CC9F56D25FE6\ +D2976B2EB968B83C4F58DD21DDCC0DDB4434633181E4384EFB89EA93B679AFE93C77E477\ +6B28F504514DA0471C49F6E5E40BA90BF167B3849AC6D7D1C05460EB0D262936:\ +238F54FD6D70A8E8E03F305A8136A4C2:9C764FCE696A60F5 + +0116DE193FF6B1F703B18EDF87610137D14EBC3119A979CECDD460C38A38817CC12FE56D\ +2110442A56A1BFBBBF4A1CF701B502C6D37AD1A6269546E07539FB4EE8612216FD3E69CE\ +47513CDE9AEEA674D6DC1719EB4A08A513DA5CF063CC9C6C037425DF4A44766516E41FAD:\ +05CB3542A26697484D30EE15EAD8DDF8B5D940F5BEC00878DB6FA73D1015B758DA221815\ +AA1FE5F237AC3F9D6A24E946097A9B1F8DB04D5AC68B0B6F164596FD087E06649F05E750\ +3617BBDE7868085FA3053C79A1C878C8FB46CFFF98F782FEECCAADBD93A087497A9355AE:\ +84BFCFD08B09C9515D703EE5F629242E:8B22EEDB409EBD8D + +F8810BD894C82BA767986F98DE5CD7E7F9ABF6E82D88AFE84A6735547CBF1E13F285C35F\ +8C5B3DBDCD89D9DDA3AA4CC4C153426E573A585C9A21A77CDC1EC886F64874ECC2482458\ +706366950A1650A30BDDB73F9A619CEDA1B806CED6E1ED00F63650C09490CE87112F1319\ +431FA016:\ +8D2769AC11176C15B77F0CB8A72B34160A1E3939EFFA43E098B50271D9B031FB9F52E6D9\ +49B150AC630B2CFA85072F797C9AEAD9F15735C69274A9BFBFA4BE9E759552B8E02CDF6B\ +F07DDCBD6C5BEE9C01568D6129676D20DE0762C5D466252CB286E0A1B7C1CE6E4BB3FA4D\ +9B56761A:\ +EA279EDFB80A909C95158D9107E7BAB4:3D899C4A9C64C494 + +E1959869B615E838C4362ABDEB51A3D0BFF2CAC32AF78E27106B1161C5D6A893A5A31B78\ +FA92AC70DC3A9CF68DC62280D963BEE9C04CEA5F1FB32B15582B37FCDAEBA18DA3B22278\ +3D2E7484256508F26BA549AD56AFBA3F5B0161AB6A4A6EFEC326477E92B025FBFD29498D\ +DCE8B9D274DDE71C:\ +95936503497BB10E8C110CF1A819FBB13DB05DA88723055D8CBCFF2B15C8DCDF12BC7810\ +ADD4A82AE8A85DFD6D906B5936189B6F0B18B9979A0C55C08E53BDF37BE251AB364D85D9\ +E94F6AE957131AF7CA475BE7F19954B45CC3C00867B9EB574B614CAD4A66BB505EC9996B\ +7DF9467A39096CC3:\ +09EBFB4079E906C5F8BE9B2041A32305:998215883ADB9F54 + +8B2999AACD2CA034908EF05C394CCEF00F816E57FCA840C6010760EFCD6E3F3AA088784D\ +530AF024FD9E3BB2B4EBC5223FD3DB3493EB6E2E1876EBBFD4BD0090004ACCEFBF3756BB\ +82CD18EE4CEEF6FBBF09AB0DB0465134E848672FBCA3BBD6CF8AEB684C4A82244D7A5D44\ +468E0F31C41B908989B7EC26:\ +51BF0E20F1FDE6F5B7FD1B72749709999147D80866C7D12E8D37CA2896D67F889FD5510C\ +8F74C62B8D044F552EE7B009F943110CD3EEDACF20DB04F3522434D5BA4E0CCAA29DAE39\ +F18CCA49EE1CBB9515C13FBC38142775ECECD778BE72497487D5A0763F20A6F84BFEA19D\ +4674066E934D8D73ECA96C28:\ +809C0B33709493BA086F146697A9DCD5:F263A312E9A219B9 + +60C66BE7E8951C3E406F5635AA22FA1869BFC560F337DEB230EC6FBEAF805A778421CFBA\ +07166136F1C1F3AE674F895CE24BEED79C81BED23C320B12C45894AF037CDF91BD540563\ +7772D4BE4B06E72181286194BDA09BA7FE682972E1D8972A09096612114DAA9CABD80816\ +B5C50B2C1644FD6ED8521E7F82540F15:\ +64A20C4BD5F7949AD3583B00651404AAD4496D5C3C39A7D463CE22238A741DE32083AAA2\ +38E3320DE7FE007968BA55B1F14AB1E88064F2C112A0E97C37CDFA9D97355692E0E9552E\ +2A71D22DC2B5866902221B7AF4BA94810E74CD4D6FAA8E57263EA721C2959A240FB33634\ +6C602C177F95B40B11E0DE004CCDF6E8:\ +A794395BE934B5BF5FB38EBA5E0D5406:4ADDE2D9335FFEEB + +C37A738A4E6144F1E5EC5B8E1E61C71AA0449D83E3D207136CD63D1A8F978D8D0B00462F\ +3A10B193B2F5445D2BB8F0C71605F277388A23677CCAEF508041C406219D8FFF569E44F2\ +4D4DFD9216D261E244DB588FEDA33EC4B87A5114378984559004ACEE5DDC6C16C2A25D5A\ +FE42C961CD5C418B44E218A749A357351131CCE4:\ +64646829143CB4A25661723F772932F14BF4898344F70EEF3186889849AD9D1D98CB4805\ +26FFE8E7B6AA15F3A9346D10111E79C809FF435EB8851907A90530F2B96A2C0E1E1A2587\ +C8AE735222967BC82A8106C604C9F2FB15E4D7EF3D8F9806455ECA090A0027BA5D2D5228\ +7E0831422377336450F45D268A6D2BDDD474FD84:\ +D9653B71A3003270F83DFC49AA48C8EA:40E4D61971A2D857 + +2E3ACE745E2D36728751E0A18448971BEDA6F21A742E21DEEE68922E89E85747EA4BCA5A\ +BD903FDD7EF705359E847687C5C132BB2556634DE165F00BA0E4693CF364CB1DC100A073\ +253732050AAF7AD77C2983532908E888A8DAD84E43A4ED29335A5515940177F8325E5D36\ +C6892E42665EEB814E6689F0E06A3C5A69D042F50EAAC4DD:\ +287F31451FB5E6769B3EAAA58506EA403BC6F47DE662BC5BDB558523706DAA72B16174CB\ +F0DAA28C5ECA6EAF37EA0866467A8860ECE342104E63687A2191F2927A0FAA1624BAFFDB\ +8660DB0FA50627509D9AB5AC422ACD521436355FCE9DA020C11D402A02EBB46DA363A799\ +9F348DD815CF60B115166BA82581CC01358B5C7F52401E98:\ +F546A2AD3A1F291A995F4C058D9C9F78:7F993DF4D373BA6F + +F51E1F304ACBAA9CA94555934652761CEC135E591492912468C7FBDA2807A61EDABF838F\ +0EB47B99DD441C54A03C65AE73B2343A9E12C6B1B7474BA6E88755C90333110861AECF6E\ +EFE5CBEE18ECF2631FEDDABB3AC0FE36DC66B1E78D8FF5162BC5323F85932B2154089975\ +01E3FC0DAAD12A51AE1F1387C8ED8B132DEF421D0727AFE59788F4D3:\ +BED9B697D1DC34037DFD5245FB74D684103E9F6B649024911976336DF5451443FD4B32A9\ +AD91B2679BC138066DC9BA6C367277EB7A7AC67C505CDDEC6300D26FF5C9E5825420F356\ +532D78080459362399FB9F08684EC2693AACB90382E326431B1AE0822BC6E3C4D67DC93C\ +301951E8635E3A19A71F0EDB63D44E53951B097B5A0FE3681E2A472A:\ +B8A2DACE13F418A8C576AF7F5DC03E79:00C100EEA0489AE9 + +DD2B20530B72F4E675F1FD7AE4FA8B0EA84B2946F1ADAEBAC8DAE5D1168C4084744F879E\ +EB9507B340EACF728D0D10786A6E8A4408908A6ED0E6198D8D1675C918462B82EA0F544B\ +DB3E194ABDFC9B40E2AC4BE61E907A70352532648C1EB6D72FC114544DB439516DF681F6\ +42D487924ABF0524C068EE4B9E45009BB8E99DE5CA73372A2F7DE78439150ACD:\ +4A4EF7F6C0933D12A4825EF1C293FEE5F95DBC69521323B6BCF527437513B878D0DCC039\ +0708B64CCBB8C3D7D1D1FC574DE35C45C2D48770DA757A65A177F8AC25C3F1F59A848E5F\ +DEDC9ED2801300F1A3ED44EE8A9F5A79924BE7E9FEFBAF6836CF18E6F28DA81F87DD2ECD\ +B48CB009A448172B556D977315F798218EFA44A794F257D250CE73AF151F74B5:\ +3EC3D092356A5B6874DEE6031785E19C:96F16B8BBCECE7FA + +5BC87836612D3D7FCBAF662B16924062C237658471CEECC0F1300C84531215406420D7C2\ +02922DF63F6864345581EB8C3345BF47D5FD9769563EAABA49A042A21E1CB39F51165BC8\ +AF5418169C8A0A9222C4A333559CA6F3DAB374D6A342D8AE24E41C51424585520415590D\ +2874F93A7919F2BE0F25438F0953FD3F8FD2804435DBE1190660227330D5B0FB3BBBDDC8:\ +077DFDB7F6E7EDD024C475FD57BFAD68BEDDF0737C1A460A589A8647212A61B33827D953\ +A2FEFC7F48E2979C4DFBD4285D747C52E3CE232FBF2307FF9F04E39C3D817B7402FCE656\ +08E599E37F208BA8684611C8859B2DA1F7F6797DBE58132E0BB143BF990D1D3D8226C2B9\ +F6BC50E8A03DB6C6560582C03A3D68F48E781B054DD69615B5A63B6136F2AB75BB9585F7:\ +11132C6E22979CB5C213191045E750FD:ABDC21EA87125B00 + +673436400DC4FB49950303A83E0BDF18E477F638B5E768172D86C2223861A86E73A5C423\ +9FF593B84BC3B98B67C56897B6417C9E5BE8ABA361E4EDBFD95DC3B15FE96E51BA717742\ +C449F635C645CC3830CC7EDD36D1D34A1F09C46C33700BBABA29EE856A86BF6D146166CA\ +975B2BCAF3C7E3C6614A03FF47BDB498BF3BDFC328C79228303AFE01BD80FAB8D54A0F2B\ +E38FE911:\ +34723A46EED388E0A273E9DE120946892EEC04EA668325C654F43800D300970DB9009E29\ +9963EB08BDE37E4AAE1B3E540EA2BABE50534B93D3988DD1F93F0E49761D83C3F95EEA97\ +9241A22A80D969ED22D826686BEFF174896D74A1F7000CBD164DFC07B92EB66EDDAD1194\ +309CA143605094BB8C330F31F5232A0A24936594DD4E7BA41E6039A3CAA6205074656CD4\ +ACBEEFBB:\ +6A0DA91DBCA54101F99ACB1362CB882E:7ECFD1F603D67C77 + +B5FDD61F8E6110D7AF03DBA5AC5342F9119F2CC317F1985CB3305E7DECD07A1787EDBA37\ +BC47AD1329D0752F4400E506A098CC71B83ED798CA67A01863FDDB8BC2952C951B46BE9F\ +8D9F83B7E0FE32F8FF69FAEECD49D2ADFD62C405104DEC61B4C3AFB6088B5369E88D11C4\ +9E7B5F4DBA284CA2BF5846275C5C2DBDFF8EFCB4AEEF12E215AD6423E9D5E6213382D75C\ +27D0E6D14C78FC36:\ +E42423B8CE44B0C3F7BADCC2E0EC469969E9531CDD4A0B7DB8646014A5D4BDAAAE109619\ +8860270A1283724DCE0E886AC9489593FFDB00B478E8D6BEF839DE633D678BA945F26D5E\ +FADD08297AEF5D3618645D200C627D6B6097BE81248B23F825FA4442C34C2F25A1E41D44\ +5E283CA3BB723681E654DCD7932A637834958D0C80DE6AE92D298B72396BBA5119DCD873\ +A403358ED479D453:\ +08AFB509E7385CE045789878C4B13D46:A3E66AF196BDBAE9 + +CDD81737DA50063D7581BC6FC8918B542E0F161D0D4BA408B5890196320C71DA508651AB\ +850C565105C854872ECD8A336CDDB5511399219D1E15387F21ECE4CE0FD896508D041C3F\ +AAFA75EE42E24B6C5FB45BC7B98FBF17E734FFD7C9E7160571FED42DA5CCE42750D46989\ +CEBC803002B72C14390087AAD352BDA885B771AFF5EAE3E6CF1428AB628F2E792A92DE72\ +C5E0234BF0AE05599A15F829:\ +B492AA4DC9B8C4CB3CE1AE1FB256D0455444D5BA7495BA36D8EA9B6BDC89881C9AE6044E\ +FE078AA9525B71FA983D3DADC6A03B5B1E327262B21718CB7EC11F46E9CD18DD6D94A9C9\ +EA923A459DBC518578D17184C6B19647C6F6FD3A99CD1EA09B97508DDB6B7439FD6308FF\ +E609A7B1660B1399B07F637D7C20B8990A652177A3E634092784A6499A994F7B2644FC1E\ +A597EFB4A4E15F08749E5186:\ +178178B147A4454EBC944527EB05FE22:B3C0BCCC0FC8C398 + +45A13F4D44F679618C049E0F6451C1DF764CD6975A08ED9FC21B7F60938FAE7EFB90D9C1\ +FC9F6EE0653319532D6E5EF4C91415360C42B13F3E9C4467FB910D617AC9A73EF44AF243\ +75B1E8A7F5A5275E18024276DB173D723B9A834E4549980CCC09D5DC7D9AC3B6967C1127\ +9C3E3847C3D1E9BA98E7F9F577E322C1985E06ABF75557540E676ADC9741DB1C4B078814\ +A62E001C3F98B116E91A6E4601CA5F90:\ +59A7C4B96EE561294D33E83DBBD876250CFDFB91AD6A1F76E112DB95D9F0A2DC1C5BB58C\ +01F650C933C9948A18C879E2115DDCF59499DA33169481A521576695AE9A248A8078F5AD\ +D5DC1E63AD39A001346BA3E3B541A9FB101B327B0DE2363BF17FFDA8CBB33142B58484C9\ +C7D888E0CD7B4482CA3A883930E35D581C755537AD4A7876E1F028C8344BC76ECBBE2AD2\ +5BDE23FE9F5293C414D2FEB1FE94DC1F:\ +0A0035EE3EC39ABDD835B30D054E63CE:6345FFDCAEC79C12 + +36144BE61EC490E90F95D38A8FA17A2A9C00B4843AA12D8030D01536C349585814E7D280\ +F292BF5C8CF2F4F2E68CB991AB0253045626AF958C5F591FE34515B29694AF39899DC4EA\ +A1B526C3AB2BDFAF51378D0ABE33EC6892EF01D281CD2817112D1FC685C86693A2734C5B\ +5CFCF6C8145C990CAECC9B318EF7F5BE8B6740B280A39FBD8B9ABEC947277779ED62229D\ +2E67EDB26F34A9A72806FE1E93A4E2E2E5D119E1:\ +FFC4706302E667EC36B915B4298BB11B0D2D1FBCB0DA35A12D1255AD4048FF593B880E96\ +C2F9451C8AD38D304148E2DC920E9B26ABA72CC05603C6DFC21CBF7B528142422537CD56\ +4E0877FBABAFDA326B196814DDF9FA8515C91CBA0D45EA8D9550C6B95D8FF35DA3F3A1B3\ +CCA42FEFC562177FAC15DB5279CA50D6A7D342EBA98A426BC7943133F71A97E074AB87F5\ +B30F8F23CD26A8309D78F69D8B39FF2DCC3152F8:\ +EAD6297D0A3A3A8612A17C4C336E19D6:66B556952B67E560 + +9B46EF1D1046A03836BA53F6EC68FA57B382FAF02606B4F272404C754F368DFFB1225CA6\ +F9A26F22B0554818BB9F784F2AA5368B42E82A4C2C1052F656BD2C0272EDF95D997833EF\ +7D1547E08E407CFBE1C996E9DE05EA5166E1236FD6FBC70A494FCA1A6A17BF4B3AB12E92\ +A78939BDD5A538E55D39E789DCF2F4DF7A8F79452FB4ACEEC4FE364B973357518A79D761\ +10353CE90D48BAB713D7B7D63AE14AFD7913F4EE74F02B51:\ +6E9151C9F82CF529E7A2B63C97E451ACF59CF00971B9789FEA5E8B1FD3071A64B312FA65\ +65A89E42DAD21C9D6BB5197C7C944C69AD6071809316E8BE5B67A775916A7E8B633BE189\ +00DD59D26612FA4624D12AFEC3C1BC39D1C9146761E0B3815889D0B3C37B860D4D56DE04\ +2D163D9F7236D1293B42822870E4797EF63FC00D3A8900E85F5BE156EBF2D97A5B71B56F\ +B0AB95FBA03C4671CBF97B300D4E90569EE9D586A4305533:\ +4E7FC8BD2DCF8D0A6ED122C394D6464F:CE96ED105D3C7931 + +DD3C2F94FCFD7C101022B328D3F11A81E8A47A9CF36AB9C03AE81433B18581E5B1512417\ +BCE9AE91DFCFDDBC5BD6957FA2602E12223E98122BDF22F0DBBCBBDD4E88CD2A87C0334A\ +B108845CB44ED56BF25FE3C8AF0C1463D2A0C6E149C218B9942C20C4FA5F42CAAE9E0FE1\ +36B238B495FE1BB33EE712CD11FC78E2536D7DA293D5E624BFF86EFFDCBDEB7CCE8B05D7\ +FD4D6D4B926C6234E602D84B3E93FA5078EEA598C3E8CE3CD9BA61C8:\ +C749DB2D42DE856439612BFB902897122B6B57B6E5B3DBE2844312CF131DB3B7B65B4096\ +D1ADA9C665C95ABA1AF299385E8401310FE9A43DCF1D0239F4C88493827F7EAE7FF5B8AA\ +2F7A1F8E42F9D3B90EE84E92B4F136ADFB4D459B22195562AD525F0FF12E64C9072DEFEB\ +31CC0331B7AD8A78DAD43E18BF84A1AC2CEFA4858BA1895A15CD29F4AA29CED0B5D5590B\ +D1AE2DE335E795CF5645FE9F9253077144F30EDEDFBFD93F47DCA24C:\ +911E1A315CD2C8126019607442FD4279:CE1FB0B32F6FB617 + +FBE74B418AB2B39F83383824C6909FBF0750738CF218EBFE913492E6B458CD25BC79CF2D\ +1BBA62CD4EA9924F13E9BE3CAAE81F9393E1B01C213D13EC7B32D42C4B896614397EBD25\ +960F2543AEB59DAF8E061F80B2D34212202A91D35AB9E9E15F26A8BB1E20E9C8645EF0A4\ +0727C705EA03600CF88F58E2065E920DAAF41779281D02BA70DF465DEC7D34669F6D0D8C\ +527AC7BD9A0EC3519C8DF317A697D4745ED94B13FED3FC8ABCA76D6B4FFC1390:\ +79E20320F675AEDA7E1D50A32C6B6C17F1BE8FE14CA9818C30AE46830A41569059926D7A\ +1C238F7AF469C19705C5EDC127EAFFA45026A39F49A5E71E3034CF4EB738775CCE69ECAF\ +62CE39CEB45D1204709B26F809B53255D1513F3F8100DCE3EC915E162AB17C62EF70D804\ +8C24E2CA11D3958CA9D06A1F16E571CB5BB39B0F28478A68BA51AB7A5C14611DB5781C2F\ +3302A15A7635B60A849D9C0080C62D244FB03670EEC92A4FB403A7BD089027B3:\ +5283BDDEC2CFCE31E61A003516C9D151:7A2E404FB6C3B6BB + +5D22783F9FF3BBB0BD89621E7C18E4647BABA0C76563CE14EB2AD5C4F6F51A49C513A4F9\ +C12CEA6B8C24D27BFED626824109E9B39B7468F39FB856D6C3946AC95C1A211FAFB4F767\ +3717EC97182CB9EA000BDE3F2905439EA5F6579FB7E6A0E8BB33D2FA3F02A5D678F1002B\ +4F95B2FD4E1C2559BECFAAF1D712AD4E37F6EB9088F81484ABE54B3A959550A2B41F041D\ +AF19167E394FFB9410D71C2CD90682D0AA6CD22D8244B6C025B1F5E877DE97372286C835:\ +811F5009DE77855B575D9BE64ACD8272699862AEAFC0B6284F4481CFC5FC1D028BA072F6\ +A2398D1DD99A731261C5E4543A0FEB7E089DBC6FA7AE9DA555D0B92A58A4D8B16A39777D\ +3368B6F698144B3E5773EF0501A41EFBFB30A1FFED14E11CAF106AAA515AB9FFF8AD9AD4\ +917155083754A44FAAFE449205D47F5D7296CA3917C575FD3ED10B26FA6A218B00374DFE\ +8EB43AACFC5E7DA3B514CE47AD69016EEBEE87CA8AAD668CA270D6328F7BAF60B0647CAB:\ +D2EE5AD0C6B1277836223D2B8999EF6C:CE3B759B6881D0F0 + +87719A3ED11A24F7EB0AFCF7743456648E1E6F170A4C98AD8296CCE7DBC9C59F761CF8AE\ +0B7719E42798C45DB57477F8D6640B5BB5A07352DDCF46FAD9CC19FE8304C1000E2B177E\ +A8BB610BDCC989D34BE946F9F37C71BEC8922BB1B067EB8F6FC6295392DAFDCE5CA39419\ +87CF2072853297020A2397A0E1F71FDA7FA381196C942B01A8A3F82874AB7D6AA1BE59A5\ +B9B1FFA357F17302A8E717E0A664400505A183F5D1D89C1E7EDF87713C5C114E10D17412\ +C28AB68E:\ +1E52C0BE4B78C8B45805586FFD14DF7740DE330877913156D11D9185A2414BC5E1317CFF\ +85B416F2882E769B74F974F0161BF7D582D25FAD24820A08A4E1D43D214E8AE6B4EE382D\ +52C4754430628B26A4E5EC17FFD939A45C7C1EDB55329A20B3BDBDE7B62746D04A07CE7E\ +2F28BE210B6B188492719B6044ACDD221A12FE6977369FF0FA5D12E2A5F492A594992BDC\ +E86A62FF3CE6E5A42897830CA156E630EF707705D6BF171C250C965F5563E235E898BA0D\ +B9A30FAF:\ +B793A8EB1336E6F82E4CCBC6A2BABE79:B573079D57C8FEAD + +BC5477DFF13EC99549F3DBA37E83231F9182CEC72D1314BD587383E6585BF97CA9FC86BB\ +A7797EA49CEC4C09433946B82962FEEBFBA4DFDEC0BC60B38A9E142C92C0B3906B461D2A\ +AB94321860DF947F584E810D502F84097ACFF6223CF77801C59495ABB52EE88CB775DB7D\ +39D566B9C13DC47127A64A325D7AA12D9B7D63A272B92D2FCA91DF310CC58FFB5CB8B80C\ +F44B5F376AD8D06EB87C262456C10E3091ED47F85F6336F3FCE3BF04C2DB9DC0F622C158\ +0DFB14C9040DE592:\ +F2A1C03F2728F33CC8745FD021011F74D89F8EA351101CDCC26D5B164032E83BC7936562\ +88E124D597BADB78E0A1EE1DA1F2805ACEC4C6F5C45616465735362045C72650E48FE70D\ +8685A2B1F982C059FA7FA04E6FF22AE885BECC2D14F8540884AB6E0C438459E89AC8D4EA\ +C698FC0C516E59ADFE79800C3F49DE880C43E3745F9F3892E9808E24CC65DF92BCFB04EA\ +A60B37D752B73C5DF02EDD4805E5CB14398F2BFC0F15ED5556E653A4FE7643CB609AA7AF\ +839DDBB2772CB327:\ +639366B19DF1C6C56B84341ECF8DC970:874E59C9D25196C8 + +C55BA1C5035F6D543A356D3FAAE8E8227D29F3D5EE065592F980B8424CED3DEE76749570\ +8C0C720FE6EAC681146ADE443AF03055294294F138275D519E3466D698D8B48AC20164D3\ +9587DD97B26C1B6853B5B274183FC73A810F00F3D748B1E96E0E7B10DA3147DD917B314B\ +8DB75EAE7DAE87210D320BF5BB3E1A44A66761F91235BEED601C87EF419A4F18EBA54CD6\ +634454A5BA0675EF68F22A7DE5592D396A9BCC181AE411E9452F9973E4CC612F72F38CC1\ +0659E477E4293A46A4FD65D6:\ +66F3195F85BB50C69719AB217566E65C682D5571AA5A6A964FC013FCD12C0462124980D7\ +C8E423A9848BC784261924A4B76B8D3D56F2B0E5EA6BABED53C45FC11BD34B32C0AD7219\ +77FA61D896275584EA4AE3587101A5CE90DA4B9E874C1EB239FAFC0DA27487ADD0473591\ +5FAD188519B7C0451BE0CD042944F3E1BDA69C4617A6CA98D22A62DC6F1581983EC1A124\ +E76CF2AD611D7697C8EB76259C679917BF3535A1C04F53082003634F09111FA8467512D1\ +D69840BDA1A1A808B8664A85:\ +AF36BB2B821552C3949B694C33A04716:BCBD3B723C5FAF64 + +F8F640858D8A5169CFFE6F222302138E35DADF658FA53F9610C4A115F0460E9F44CF0259\ +AAF63714277B493E94FABD920F22E2585D0A3AE55812751A54D3E194E733FB14C6260677\ +E1D8B46F94B69E31B83F6826A93B6821C3F3CC6B64138650CAC4500447083D66422EA346\ +2D978FAA70A5D6369DE9FF066FCCC8AEAAF7C39705A3432C8F69D67179D92893CA230E8C\ +B0FC559E0CBDFF0AFB3108603C2A9786E2E7F6BD965F1098236D9910BF228FC8733F1687\ +27A209F57E7E4C6AF7EF620BB158C864:\ +4CB818690D084522ADD573C3ADCE75D50A65342D16C2BAB23153503E1D163B17E085EE92\ +80DC5C1D19B041B1D9ADC43D2426FDAD9B11B21CAB5E3AFE0FEC9CF3A9117C47F39066D0\ +041A1B7282E10F2F1791E7EEAC1DE2AC70A1A12BE2C646B2113F41216B5DCF6474B9ED8C\ +3AB2D1BE23A5AB533699D876DFD512661D6B18E9F29376AC0A0B12D7B6B2231EAB5D61E7\ +F7ACDA7503FF8E58E320980E83E877738B749C89C626FE24DF12089B973E50815EDB143F\ +21DFBA48C0B70DA7C1DDC43233AEEE35:\ +1CC4ADA25984BFF53CC86C7364278440:C9CB2BDB19911DBD + +BB97677E03C9259E9096A6B03EDFF049EF942C5FFEADD4C59B8FCC713E2F42BB547D58D9\ +487FACA73248BE2C38DCEDE9310B7844D68F3D0EFE4E1925433476D1618769306A571E2D\ +4768715398CD560B52CC492213F8BE3DBFFFBF35877061BEE5CEF46A8B8D43FAE2E41623\ +F0DED34DFB8DDE42D7492E75F2329CD4C17A8B86D60AEA10A8C68078955004B8CBE4BD80\ +E61FE9B01B9CA83EB5D902819D4A6D8997B75A7F1E86CABF7A5D7C8C44B93B66F8C80D32\ +A7438900740BDC2F7DEDF4B6E729FD5B8A1C8D5F:\ +B20E712CC5B0041E191ADDC5083A6014104E8DC5021B477CAA5AFA6395B7606E68640FB9\ +EF5E208FCF0515575BEA9C49FEB32749FEF89EB579A869DA3213F5DC86A4AE12CB02BAE9\ +D2F45AAD2B5FDFF1FAFC57AF290B70E47CD00648ADA75BC476D7E048DDE9D138133F081E\ +AA0C1475E0D1260AC0184CEAF6F99CDF5140CBBC282009F72272374E946A26BB2F0214C8\ +D7DB0BF7676CC582C8DB8D14048B99F7C99F550A4B6EC89D1B1D4A067591FD411D206878\ +A5F413F0A3E67671F0FE340811D6A77D55B6096D:\ +37910B573950EFE3AD2AC0F3229F34B8:6DC3FCC797E8B292 + +0BDF3471B6A535F918863F7C902519F33BF9A613CD5B265C20A4DA957AE43DABA8185A51\ +2C7215D58CE22B24567A986455AF60FF075232B9E540C6ECBFA71BEF3CBA65B275AA1A74\ +C91396CFEDDB7E39D2EB07C407C070CEB3486AD025295BE09FF74DDE2F1DD062EDBC294C\ +CFF0B0B3DA798E435EC727AA17E1088B6F9E2AE415A19F88A87F38B366EA6F3DD01BB05F\ +D65F73F8F97474EE5985400C25CECCBEA9D4F0118F81264933F6A61C307D148C43853C0A\ +5D93DF6EEF2A2206079850A05E08EA9876BA4F6B202E810A:\ +5D5C57860E0F0AF71142FED28B1FC0CEC703D8746AFDF5F93BC9B80F4D0A358A3B74EAF0\ +E128BD14A14A4F85BCF2FB40ECA5083D60473FFF6396C8C718EA44C5E64091F6C268CEE4\ +33D81B139E0532E7684CE4D2392B32383731C04829916A2B73F9FFB7D4BA1B9BC95E9D5B\ +BA4112FD0ABBF2BB0A3C5CD06FBF52CA87E91EF399E051309230BF61F84CAF9476787B59\ +10EC491855020A2838D19313FCCE4893030988162A8873A559522F1D4FA7BCC82183350F\ +31D0BD8CB4C846C72AACDA246330FD4E869D900004A5D655:\ +31AB675C93F77A7F5FE7A829DACD46E4:9200A442F4CFEA07 + +04DF7F049025BCBD7206B4A12F7E8B599C74A616A91A7B7A10F148DFA5DE56AAD4DA35DC\ +9F7580151EEF0F87FC3E630136AF059FC49AE77AA9809F7019ABC9A409E8EA5801F50671\ +672FB20D5CFB2ACF5B86C7FCA4805AD6864FA0062DBA39CCDB369FC7FC5F19047206A4E0\ +CBA96D0202AEDBBCADF69DFDAB7328FC40DA82491F429AA770E177D775F728FA32AD548E\ +4614162F84FD2EE5B8BEDA5BE1EF85460C4665782F44939DEB7571B6E2598EF78BF0661E\ +5D4E6DA2F493C1D0F2E6073302A19C26F2707BDE2D5A6936CB4F9F6B:\ +1111C0D8F2C9577D3707BC247D460104ADA84F30DFD8A8EDF6478092832F2E35200445B0\ +13BF16A419C6D231A66F34C76C4037C62C377654CACCF9B770F7339CCEA0DACAFF7DFC39\ +3535293E8B347DA29FB207C369853A9E3CD444C67CAECB7AE4DC42B60F3BF0EB2ECEC7A6\ +482F1BB767300C539E8FB9046B31A267D1C9ECBE997EDFEF4B46A0DB501F4FED4F81C99D\ +C15FEF56D4A7ADCAD808F8C6B16A4F62CC0A4C39F57BAEB0914F829E1D4E4B72D93D8167\ +BC3CAC068C327AF3D7C887B65B3400FC4C6E6400326945F7079C6EF5:\ +EB2BC3806990CEC6A01D863E1AA28056:7056216A1187E1C8 + +963524B3D92412DF49F8DF7CA10032FE6C56ABD03866ACCAFA9E45FDBA070FF683A52960\ +6900F1C7ECD437B56A74390858E4D3276DC8DCD04215470C0AC21611D8EC1EA9EF8E5120\ +06D876420F139007ABEE1397247BEB37DC37CD237E3909C75D576D8D37B5FF9F7B078D62\ +79A3B0500F308F991256394F78B7616B28CC6A622A98B43A9531BA25917F6D7BDFCA5FA1\ +9DA4F372AA871C7F253C065A4F923E734740A5534474B5B661164B00605430FD112B197B\ +8570D27A3B44A4C367471FC58F533146305CAE20D15DFD9539FA4C6920F09F73:\ +36FA83EAE79BCF08ED631AFA6C0619ABBC6731051763B61D2EA51B5D859E5069B0FFB480\ +1EFE8DC3EA79D9AAB849B98F0DC180C3A7BE4237A0283372B235553692A926F8C20B9466\ +935B5CF7254496FEE811BE2406563345C16ED4D37A1609683B3216DA5D01CEF1E2C0CC30\ +537AC8A9ADB668C0A8D7DE1EA14AD9619A064B1D9C11B8A224D76ED68838EBCA0D323D80\ +1E293EB2AB9D2F64F3C1B4588CBE074446A0EFE77C5E58F3715691FF50056B047444784C\ +154E230AB3C27A36DA7E61DB7774C9B402536013DF4DA7895E51AF1933A458E1:\ +7FD1AB8DDB8343643C4DB7D90BE1F9C1:F6CD6CE2D5F1DB56 + +C1EA094DE4B8DF3E530F4E75E08DC4793EB744FADB50E94D0C360CA08FD184E5B6E8B685\ +489335C6173CA117F2CF638CDCFF0F0E3329C36125D8780F4589EB76EF76AD722A359C84\ +632865A5ABC386F838EE6DA8E6DD96B6DD53C3AF3EF08315B71E53E442893EAEEF6D0022\ +AFC7D08DAD0DB051CD709608ADF4CE94988476CA95EEDF3CA63328B0EAB1211082655417\ +2E3F2ECE07C25C62992E81985B9B1D9E3186AC83B167D206EA7B180A656BB4A8C5F09DE3\ +9B2ECDBA96E1354706449717BF720E9F756FDF4074FA9F5B3C0016E32B94AAAB9484295E:\ +E66888E7F4A179F83B178AB7409D2C82E014922644F2276D4C308EAEB9A9F42F4062EB1B\ +DB77EDA72C4EE499CD970F1583F284523D375C33D5AFE5264220339604B46FEC19BF61C0\ +E7B07F7B710815801B02A4CAE2BF77F28A0EAAA026D1136580FE1B8AD1B1C40DB1A23FF7\ +878531DFE96B18EFB5CDC34198D23A22F005DD7DFEB91359DBC3BCB1E840A71EBF85DD94\ +663A906C315A1EAEA2E5FD673BB56B23B98D2F54AAF3E82370D75417DAA68C05CDFD15C9\ +592FB9BE87B5C37476A2559E56C4D95834C48ED6B6B0E4661A6F8017A358D0DDC9FF3080:\ +F674FCB74F8175532C3B888AA1F685A1:FD402E1071C463B0 + +47F823E98A8F3DC6E872A177EEEF167E82D23862AD0C28E8C2172EE541F28863A5530EC4\ +2EE5E6462A467BAB8372BE75990369F8FC299C13729CB508332906671E0F8BF40A82E865\ +51E9CA7FEB3E0FCF8BDD5EA5539756802A450D09637978E91A2DD4843DDCCA8C63EDCAD0\ +2B3AA18744FEF1C78D9618686E4B5A84E00069328F1988CE852AC7B17E2DC24280502154\ +D9B1604654CB54EA5E4D069643D6A43D988555AE9CCDF057F896CDB600ECA135406B5115\ +8694ED6C8BCC898E2E4335A9432157D306E12C77059CD3B296FD9C9A225719861D042ED7\ +26BE7302:\ +42300596CBD9EC098AAC697D227058DF9A88051904604063E95C509F9F03869C68AAEC10\ +63701259BD652E9AB275F07BFE164057367A74EED02C72A96B3673ED0510B782E6F4603B\ +ADA717221EDF098D13EFC76A41CF6261D36C64D7B747303B601B3114EA603F9BA42C12C3\ +B89642DF4AE2797569B8798604FCE8BC7906F09310858209A4F678748610DB9DFF24BE79\ +D3D5D41A4F0A449A7EA03628959E5D44B801048BD685A7541D57E9AEFD215D45227276BA\ +6B737908C2AB5066CD3FD555A69729B711ABC683E7236B3D0D82F112888006D30CB1DDC9\ +FD680FDC:\ +68101E5C1C4C16FBD08F90DD040E222A:F2B05714F3B87180 + +1D4C4CF8F819F57243A3CED7F2D8A284AF2588B0C808141A698C1C2C6B7470659344245A\ +D162D527A3E221AC8822668541D10A536B015E8AA35268321144D6D84A199FC147E12028\ +A3DA9171E8705CD65A54210ED4EAE211AB1F864383A2A9AA014E62ED69C60DC32B540126\ +71313B45319CAD64B0B26DDF9AA48E5D0AFBEA3EE2821459CBA5F4FCD798A8647526CF36\ +55E0421EAB46B558B57646C56DF3F6C62B92E8BA3D818811CE7BFF4975AE434B23E095F5\ +942827ECFDE9954C6823FD5198E0002E189C63006914672B08A61012FA7A37A800BCFB3E\ +C845D179DC210044:\ +1B98BAFD01369C2CDB5004819CA0E2075860A4543B1A6564B32F097C382F944436065859\ +9A71C29CE4791683E436DB052DAB361A68D6DBBE3587AB2F6AF60A102B59FB62DE152DCE\ +0737B968750174D95854AF51C95473D17060082051DCEC1766DCEFAEB2B0754D9B95980F\ +143DE1D6676DEB9FD6EEBD01652B4166072974DEB8F26CEE33D918CCCCFB915253797984\ +5E86428145E9225F69BFA8FDFCFFC80CDB0274B48522195CFA77F33328E472FD767B6C3F\ +F39B66CC42363018E38CFE221039EE5065B7A64FEFFAA441B6E87003DF7C60790B9CC46B\ +A6ACC7557609BD9D:\ +CE1972241FA1F27CF1AEE36A51432732:4DEDE955E0196744 + +2089A7FDB2728AEE9D176E603055E77ADBF6861C98A185B642BF02C04DAB8226570F746B\ +66C1AB8271FF590CC51A89E93F9C6108EA593F9135AE64CA62C11E165924C4734332BC34\ +C090E7383E7E1108392CBDC103C4BB847C443F7951F17AF7C610CA07889FFCB27B40AC17\ +F8E0594D6DEB391E3D6132C3998CF6F707CDABC13CB702F7F0E97F266175F0C1282682EC\ +FAC95C8A709CC3092010D48F58DF41DB72E04013C5B5323155CD2D9720E0D40B13BEBB08\ +1F97310FDEE5D00FCD7B5E5C7FEAA2A4FB756916FEFE38DC0025CE7381D83E52DE05B09B\ +1273FE3B16BE372DF94FDA35:\ +7DEC8416E69DCED8D5B6CC3B831307AFC33FECE9A0567DEE0A5999C804CF01FBC19AC1B8\ +555223D3DBE6CA50BB096A7A87ACAB5A5F0ABEB3111E98FBC09897708A18481B51EA78BF\ +E3CCB5AFFBA10F4B980E313E3ABE98EA7E13E38282778514F70D16F7940B6E382AA77BFB\ +4044D6F8EB9D95DA97A142DFC876746FB8338200787D3FA27905E57FCF861BFC8478745C\ +7C2DACC162115E5AFBC80917ABC5358957ECBB65B593010177CB1CE947235A94721541F9\ +0349011188A860D1D23CDD64C3B8D101A87114803690788337CC075B1D37DD21097FC730\ +E528D94FCDD4BE1E9D8FF00F:\ +17192110F1F1B1279CD586D5FAE45F4A:A01800F5D6B63103 + +6AB1E72EE86035D1E1E92B3E79DCE8E72C77E3AE2C4C17A345CE25C373C5B95833DF02C1\ +F34ED2FAC60F6EA77762C8F01AB976DCD2F24BD46136314AFC6F1336032ADCBEB1642A7B\ +46C8CC6B122D67C1EF3E578B6B4AADD9CC655FF37C2D7B5CD3878C32C3D5B0455A2C1DC9\ +FF743EF2ABBEFE2D8214D48413032133D821AB161F300CBEFFF376EEC0051D4A769F5203\ +E87B99DE52EB687EC12D747F2E55B84FF377F88E3F9B72900BD7A8B18E970FFD41BEECE4\ +D1978F25411B7EF8991122C4B4444F1FEB3E88A89E48B3CB721A62EAF0784CA549445852\ +10A91A593E2E3A02063D1F76BA62B997:\ +0D6121F6EC196C1AC20C818918A2F2683877EEE0189D94511CDEB2755D203F75851FBE49\ +8818C6013098FF6200E2262328B8084144CD2782DB5BD5C51E64B3FCC2F2D789B9CE3899\ +29E72BB65A264EB554213AB772140D7BBDAFFC818B2D6D0BF4ECBAD5E984BC17C1E7EB6B\ +1D435B92B2E1C5A8867233DD9534F3898C7F64E1DF8828BB765E382F9E2A46B5FC9C3802\ +2E1E5C7D09E791E187073DDB688921D22172AE4C972B1B6F802D4FD75A997803B9B87E9D\ +F2CBAE978C3E6E1FF18AC8D56CDEA3B9B1E9DAA74EF3FEFB018EBD9902AD4ADDC67BF010\ +0D9335569D6499563010DD12DD3E23C6:\ +190834E408E085E8CC3793E57146FEC8:1DD4835D46E42E15 + +12025BA46EB9326EB77DD3729B51E1A2E845C031B89DA66B8D73C02AD33263522AF4B92C\ +B5CB4BB254057012033B4D8A147AF3DDE90B7951DC0FBAF0C98D4530A367E945D6BA4C54\ +F57E9986A2452AFDDC8D64550823487168529B5D970A6CA0FB5A8B73D4E9576EA334E418\ +75DDB2955C1E81A8DBCFEAFE660C9A594AA169FDC78AB03783738175B4C974E28F8DC593\ +782C9AB44DBD49934C3AFA35E12A8ACE7F02A469B1A7847461D00B85D34BA01858B624B2\ +A50F192DBF4B7ACE9082FB2BD4B9E4C39CA49300FA69D3C1755B839C90184F7BFD322CEC\ +78F8221B0A9BAF3845AFE7447477EE4B1623B384:\ +6BF880E9AC252DA1FD73270B64018ECCEB005CCC89AC7D48B48A5E61F15D21F5524B0057\ +136BB21FBF084BB16B1E5D09C8BF6082AC285120945B63522255C943D137F76804F5B6B5\ +26459E9FA64B3B5CE1B2AEE7BBF621B864F42556E0251FC8829B536F565E929B5C61CB72\ +EEE11961B52A956E4B2D3BA81124952F6FD8B4EAB170544D0ACDD2D97977328549F851E8\ +9EFFDA3057D193189EFA71B60100C4719CF0D83132327828C48E452ED59EF0709F295349\ +E1141B003BC688800C86F3B778A18678403BA35309373967AD8B6F5B225B85D2F0C16C1D\ +5A155023A0010BD0FE1EF31139F18FF8CD9606C5:\ +B7029C1C72337170854CAEE83C38A031:DF167881D0D693C5 + +79E97D129AD18FC0B12C3CB00C872794D8AA7647BD743E507E0A67C0434BC32E58AF6F72\ +0668DC6FBB1CA58A0774F01AD16AD46A83A6A493719DE8D88B709632DD1BE56238F6C95A\ +599CC92B9B84EC18C43E2598C752BB9E2DD1AC58395A8278876AFE7F152F72934B903FD2\ +3BC1F76718A3518DB74DD8CE3E41918E62133B99742A5869450B09854ABA3E9466B7C44C\ +ADF80E126CBA30CD6117755701F6F5FAD161159425B197C4B9804B5A7940627D2A2257CC\ +D7645512002C4C5B09BC0DD4919AE3C96F70FAEEDD4E48CBBFAA2791109F2288B641F3AD\ +145B37EE68EA0CDE249F1669604E8B717A5D247A8BB25AEE:\ +7C5B40D0A68AFF288C04331EE8EDC20CCDC98512858E54C8888DBFD550231D7463F1BC49\ +3C23C9FCB93EE65F025ED0A0F470DA7E15A97B900F64D225B71D7C8CE6511A4B74EB0A7A\ +FE7E4EAD04517198635BEB48FE2C41D6552AD5DD48936CBDFBC9CDFC35248AF5BD85360D\ +D8A3BBF4CA4E87D6E345094CF9AC5725E32736B2AD12C0FDB4E9382372FEB011F6F7D222\ +175A92698D1D74B3795EA05C99DB64FD6E439B5DCF85859CB4D9398072C8843BA1D1F650\ +D5F2E2E2BAF2F1C3A66A10BFA879FFBF6203118771CF893982AA710C67C2347A8ABFD74E\ +B814400C306BB95458FF3EF850DA5E0300A1ED39A1B5611C:\ +F7430DF9CCACB9230AD4BC7AC46B52F0:F9059FC6D69FE7A7 + +57097A044B43E7A3E111EA95D9111CB2B7440A54A834416FE02A4F34C4C8C34741CB340C\ +F66750A9683E23DADFA23320EC4E0A0BBE692A8A2F816863BB078D7FCF6C056D5F2E8169\ +CD639B148A779618C32901CF37B85DEEE483DC0F30B522504070602CF032EB17CC48232F\ +86FECA67B63D06F0B25C717A62676B26DE840AEE70D39432567EA2868ABBE2EFEAED6E41\ +7BB02E0A2E9C30D7FF850503380343838E7EB155E1901547BCE29254F27DD1979C2608AF\ +0EE05696D5F3D3F678FD457AFB048E41CA852129B5D78A619231B60DE4E19B60E2F699CF\ +09E832CE02EB63543C02523C092B34FCFA10BF9BFD9E32766E412A27:\ +BEDB29A971B27E7959B48857AD56DC1FF2776EC258646F26C935928D4B1F0B874F0F34B1\ +6C5E1936D6F5E2263119EA967A9C441F016431059CF8B54CB1AF52A7BBD1D5F9C378E302\ +FB9C9910742D7E5FE8777F2F5D976A569D54CD54F37524A0FB9CB5BF5EA17763171F52D2\ +C823C1E12A99C2196C45FCB1AE3FF170B05D5EBF8EDAD51D7FAB7B6357B84AFFA19DF67A\ +DAE39C964CAA610889E1C79218C38762B7A4B522132D9F9235CCF8F8D810BC9D7EA44C77\ +599DCFD1404EC6BB219D1F1916C0685B23D79E57A280A1D3FF5356F948F15889527C4235\ +8A137CBDAF7ACD8750D5D317F295B821E450C7114279FEFFAB4121A7:\ +500E05FC7472AE721E0B9DF4629EE350:A791B3A28B063D6D + +AF72E9E989D375EF3D4B16E56B025B0B5E3732337894E5E5AA08D9763E905C625B782AF0\ +530E2E3C8BF1D3F336BD13208FC0A1D7F0A8BB91E3FCD7C9E45541C29809C8F7589042CB\ +AF994C56F5F96F10E2140AF452D376B5DBBA2C72542E1E59D63C99E08334ED6A82605737\ +236D4AABBD45A92610AF0C2852B2A63CE0A0C8D1D281D1002C8C37942791684475B10C1B\ +B81E8CC3E7CA9CA1BE881113AEE41857F25E5C6D404F903E93F16BF912D767ED6AD2604A\ +C8AA5937303699168D8B034DE7B15F25DD25002E22E7DF90B636457FD62E83731675E32F\ +6052BF1BEEADC5E65F1B2831A2702B0377816792EE9DFE04BC6410E9C597B633:\ +936EDF889D6629BC65F387545190C03C4AEF91B9A8A13E4E51B02A9DCAFE990CA303DD9F\ +F81EF1C83754657D4C2CD8A89BB5345DD280376FF8996F2204BF1ECADF126D992172CF45\ +2A5999C1CAA455A0AF9EAE12D8B5B8CB4992F215707542625DACB4C460ABE2A97B804ABA\ +14F365C4A99EBB92FE4174A59D74C0D942D75F920E46264D3FB929C60ACE11F4982F6E5C\ +DFC8AE73DCA838021D898E22916333075268A29D8BABC2A78AE5E54BC51791679203B812\ +C4CAC0A4251224C4E509F6677FB140B557665BD85AC3B3EF2D204129A84344654D6AEC97\ +A27C8FBE1D5FBFA272AB20615D2B97A31AD82D92F6457BD8B7A35A98CF8D8384:\ +19740BD949A0AAF7A2908411B588E75D:D0CB88F836751471 + +5C679ED0A8FA89F7763427FCEABFF3640D680E74B633889AF857418D8142B83322A084AA\ +E7521A5DFFF2C8F05A345D05359BFA873E24CE2259F98B9F40615F3CFAE9736629C988BE\ +0949924060A5A85A59BA733FD75F53F991EA3D37D9C53C58C4999F380DE813B73342F427\ +39B169AA3568834F3D3A8AC0912AF8E3F116B602DE32760D5F1A4DBF7F71F783E41A3AD2\ +73E54B76E4A6439C9739210F5A2B5FAE2806AB5811D22B8F5B5CF68E80B2921F2980C285\ +8861A66619CDBE4BA9A3B2F6094C9774B5F9C07D8B99BEE0E4FE02E0082ECD24497236C8\ +621A413E2F3DEE93F38E98DE28B95B621E8DA964C7419AB2DB4FBB5ECF3A9637697D35AF:\ +C5C9D588A11FC4EE03A6C8AC33064C73DCA48BF7C3813EDB9495FE0DEA94FE7F60B5E491\ +E802A06CD0593FB8169230144BED6A76CB353C564DFFEEC8793F28E659127CC9F4C25D33\ +1A0718AA2A91B463A3A686DA4A037C4217EAF907B70916A70229EFF66118D932F1EDAE98\ +7CAF21EA174582ECD8CBEFE7A3CE1F2683B408F56A6855A56BB9C8CA9F8B334F1C9F03D6\ +8D69CF500C0AAA729D0E7D8C40B9199D9A8484EA45F7A483E8052DF531541DD3E354A31D\ +7B2AC271A045A72AF306163DF714438930D6B16D15A1E0132804DF1A94C2CCE769FE37B2\ +0E84E147748653A2F4F6EB228AE7C1AD6BAEEC853F17C1AEF07756C42E2C09AD84538D26:\ +8CBEA7813B209C17DE9441053D8CF013:DB8858BD18B36B06 + +CBCB57CFD5F6E8E9FD5F987FB13C1ED23EDF09C2929F7C01FF6D4B0AE61E4F1B3A5CED6A\ +CBEEDF34831C96B9CAF72C2551BF6011A432DD25540EDD5C75E1018F34846404A912F23F\ +580BFFFFAF8CEB875E7274021B5E2B47F794ADB79699D3D1C6D26E0BF46203C3D4422754\ +6056CC2708224FF3FF9C5463733F41E10804A4F05F8DB4B2FF72B96BB4CF240A2EF2FBDA\ +20E7C91BD7D4E1F7F322533A03F3368A88DD08C36F21EB76CD59AA5C0C3E2537F7283B6D\ +42F6D24B8979246FB8970B6705B755D5EDEE4D7F71DF1595F9953E954D0775DAE56F1840\ +09764B5DF00C136920F887F4D78E8932E671455F98280317FAC41C0F5050E4A1CBB7CE46\ +0FE75EF9:\ +E5F790088393EC494F34AF1B4BE73B63666874BF31D74D64C749A0DD067F6BEC681AA339\ +6CCFFEB2E30572C7F9975727EF566827E98CBA94093499E4F666DF3BE4CECBB861AE5BBA\ +78D67B6686690A5A5069D47B1D3757F6BFD28F734A06F9E37980C574D2975F0A9925CA94\ +88A11926DB59F3B00639DF25C3FEC100688AA640AC67C9788103A9BB85D53E2420AB3374\ +953F00D49217A1AB8883B71D46D361E245C6F0A5F68A6154DD94D8380FA853F6517B7162\ +78F3CE4C75ADBB27B9F774C2FB749DA9FF98E1E52FA2C0B4746502BF360E77B56E623667\ +395A59F4FCC2EFF4D1C2476B014785404F62AC1570C464BB0DBDB3A767A2D8105BEB8955\ +1356289B:\ +281866EA198A1CEAD6E334039B2CA436:F8E76A4A26185CE7 # MARKER: Stream Ciphers @@ -27755,7 +29292,8 @@ BD348966C075CE6B78BA2918258538ED 00000000000000000000000000000000000000:\ 2DD5C3F7BA2B20F76802410C688688895AD8C1BD4\ EA6C9B140FB9B90E21049BF583F527970EBC1:\ -000102030405060708090A0B0C0D0E0F +000102030405060708090A0B0C0D0E0F:\ +0000000000000000 0000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000\ @@ -27765,7 +29303,8 @@ AE39508EAC9AECE7BF97BB20B9DEE41F87D947F828913598DB72CC232948565E\ 837E0BF37D5D387B2D7102B43BB5D823B04ADF3CECB6D93B9BA752BEC5D45059\ 1514B40E40E653D1839C5BA092296B5E965B1E2FD3ACC192B1413F192FC43BC6\ 95464554E975030844AFE58A811209:\ -1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A +1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A:\ +0000000000000000 # From Crypto++ via Linux kernel 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\ @@ -28026,7 +29565,8 @@ D2A3318DA4CD57CD133D64FD06CEE6DC0C2443314057F17217E33A636D35CF5D\ 974059DDF73C02F71C7E05BBA90D01B18EC030A95324C989846DAAD0CD91C24D\ 91B089E2BF8344AA287223A0C2ADAD1CFC3F097A0BDCC51B8713C65B598DF2C8\ AFDF1195:\ -000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:\ +0000000000000000 [Turing] 0000000000000000000000000000000000000000:\ @@ -29931,6 +31471,2530 @@ D8C1D4BD9C3086F1FDA0ECD33C4FFAFF:72D73FE9 # MARKER: Hash Functions # Hash function format is input:hash +[BMW-512] +:\ +6A725655C42BC8A2A20549DD5A233A6A2BEB01616975851FD122504E604B46AF\ +7D96697D0B6333DB1D1709D6DF328D2A6C786551B0CCE2255E8C7332B4819C0E + +CC:\ +0309CD7A44E6022671E84C43CDB92F613931D1C6B71467C039034B1263C2BF92\ +203E27604BC53FCEA9C2DF3B10862C9B6FB6E8C617754EF49A2B80F51C74ACD3 + +41FB:\ +1FD4AC6551D39EF27B5F1F886D7A3A72EC60E0AE2966649C3701952F29B2DBF8\ +58AB6E18101D038BBF019299C7FE5F62A4BC3973E089EF929AAF25B9A8BB7D39 + +1F877C:\ +8987D458CF27D4C1B1DDD115FE5C15A67AF431561812B1D2028C3AF0A52FB8F7\ +334205CBE003CEAB1446261550870EEA6921C2315D750F9C49AD7877590A9BDE + +C1ECFDFC:\ +5A443348F0B3330CBA5060B16EF21D5597ECDD597603B3E86999099C5595BE38\ +F726D10090472DAF5EA77315B6BA62B2507A7C08A1B6786DCB30148DD1517882 + +21F134AC57:\ +C1ABFEF8AC91FDC20900045A226EA8D5FF2E3E5D0F00CC9194D19F6546075558\ +7F72492E5D5F5A30AE63F95E9DFEE6F07051A8E9856E701451BE1CC58D320E3D + +C6F50BB74E29:\ +B1EC7BD5A91DE2480BEE26C93A84E38030E2B2BC469B7D4A8D91D32CCB889805\ +436739DCB5A14B1D4C0811EE2A0D9A667C0FBA00F48800F39AEBE8D7DA7EDF1C + +119713CC83EEEF:\ +8652D6C03E8B42F46D96E2357DE252C9B4CC483C32ABCADFECED70A07C8E1C8B\ +637A6FA1E278C8BDF651D6FDD8A29A48DAA8ACA71C2277F709A83A80C62C5DA5 + +4A4F202484512526:\ +86E05AB43DEC6C078B18369AC5485B4FAFCA9C55C36E736BFB08E169A2667C67\ +C14A7D0409FC735B18618E84483E1B39DA47A41E48915096A8DEBACA7A148A03 + +1F66AB4185ED9B6375:\ +E072E9D923E334A5C0E129E46D4EE6E5FA2A1494F6CFC4D1498B80470A0B920F\ +2B2D56575A771D8271205D973F23A8DA0FCD3DE5E569269B50B3BD823DC8D955 + +EED7422227613B6F53C9:\ +6D8B04C1DAB6BEACDF7410B9FDBC96E74D9FB11A949DD164C817BDF4ED2DE978\ +B61ADABF27BE4FB8DDFE6B9AADEF8038C217BC56B17C78D19A80922CF84DF8F5 + +EAEED5CDFFD89DECE455F1:\ +66022F69F321D34378271556AD6793DEE887BB6DCD07344CB0C9F9FD8F6C9080\ +F296B99D7D42A6B4242A84889F41894258419CE871D54F21D78AD5BD7FC81A7C + +5BE43C90F22902E4FE8ED2D3:\ +BF48CFBDF5876FF02D095482F4DB28693A3D09B9FCE1DD25BDDB2F80D1100AA8\ +1D166E37421A3281B9F25A981DCD6741272E3F4E596B5003FD86F85C9C31BB92 + +A746273228122F381C3B46E4F1:\ +99F9C27A26186098430839356FD651A6C203E39ADC06EFB3A6C35C3265FE37F7\ +CD3B4EE520218D820F3189B44341EAA6CD753A472A8FDFD7386CB5E3A1D9DBB7 + +3C5871CD619C69A63B540EB5A625:\ +2630080B86DC7DBF5AC325F645B94E0A5FA967913AE02BCE4B762DC03E8DAC4B\ +463A881DEA606FCCD2767F6044040DFACFCB774E19FBDBB8CE89AF937077EC0C + +FA22874BCC068879E8EF11A69F0722:\ +9828CAC020097A5A74E5817EC37034DC0346F07E0CC17AC03E386C7045B6977B\ +9B276EEE6C591E970D0D1F2402515BB63E520C6737B4131BFD114E8D58B4F035 + +52A608AB21CCDD8A4457A57EDE782176:\ +7BE3BD61CECEE09EF1160C1CF7DBCF94F5E1BEE3A30F2B27B0580C3BAC5D2592\ +8291372CE81237B867D4CA09868A0CC7984F2CFA4EF14479761E2EA58FB78BA6 + +82E192E4043DDCD12ECF52969D0F807EED:\ +68A2B3C34D5E023F3BCA7508BB0B5E9BDA5375E245FA394D2CF508A03B48AF97\ +005B3A4DBFFC0D38CA4416ADF504745F94FE9B0D3F5CE334DA9805F1F3ECC978 + +75683DCB556140C522543BB6E9098B21A21E:\ +345692802192594F5516D2B22215DECB648E6611B9A24D159FD2978BF712846F\ +1FCB61F1E5A5AC25832D7E7BBCC0D0FF2E55EC2C9C90EC1E0078697117ADCFAD + +06E4EFE45035E61FAAF4287B4D8D1F12CA97E5:\ +3E3CBB918CF27C6A73D0145CDD3A8F159C56AEF938F69884AC6FC8C3207593FC\ +8D3E712ADFF0CE52FEAB8B693D8933D87DCF8A3F58BE330B4B5DF14EE3D635FA + +E26193989D06568FE688E75540AEA06747D9F851:\ +D1C6A2F12589D77610EC236DB751DCAFEF5A9DFEEA63E307DE01FB4B852DC577\ +6CD59CC6DC2369584B9DDB214BDDF5D5C89D0D1EAC9FB8F7C0F041452CBC11F7 + +D8DC8FDEFBDCE9D44E4CBAFE78447BAE3B5436102A:\ +64659D7B159C8F276DB1295039EB6FE2435405DC1A81BF4575B9C27A2C41208A\ +0BD331F34A60DFF31AD29F8730C0786ABDEE4ABC767092D448CEA3F97C7A6976 + +57085FD7E14216AB102D8317B0CB338A786D5FC32D8F:\ +6CEA91D04E9D4A3C994BE9BB24FEFAF967B4DE36D2566F368C04CC2ED9FAF736\ +DB71170C207F31A7F08B7B8D634E7C38FD591A38948DE4ABE70CC64F3A2EE108 + +A05404DF5DBB57697E2C16FA29DEFAC8AB3560D6126FA0:\ +5B5CDE06BF8B5AE80A67D96306AC7E96AD15575195B269378EA65C6F23DFF53E\ +A4E02639F3EC61D640D3D9B2776DEF2FBB3B8AFA1FCA3AA55BB5208788671770 + +AECBB02759F7433D6FCB06963C74061CD83B5B3FFA6F13C6:\ +0374C843999A2898BD79A0CC8DFB924E7BB9E5CCAECDD151B502C1A234F1D369\ +1F3CE29D0BC6F044A2CCA8174F7537078F3FF0CA73E8CF1D2040D25D1AF3295D + +AAFDC9243D3D4A096558A360CC27C8D862F0BE73DB5E88AA55:\ +7F1E7A420B60E6B42622E4B5E2900D6CF01230C962565A6F7CB8270C8CBCB4E4\ +77D171E183B3C856FCE7369FD25D5E285E21777E3C738090215D97E25ADF1FF6 + +7BC84867F6F9E9FDC3E1046CAE3A52C77ED485860EE260E30B15:\ +52A8179F441682C0CCF7F781C0CB905442ED82CA60ABED14BF032DBC5202CCE9\ +1A66369424DEC0E4C45AC16F156A9AC7982FA4A7AE941B4F24F8DA7A4FEEC4C7 + +FAC523575A99EC48279A7A459E98FF901918A475034327EFB55843:\ +50EC175DC458FB3DED1E3AF7CA87DD6CD08FD89B0BA403EF666E98787D3E38CA\ +48946DB41F38C8FDFB82FD0AA71B08D9069E7136775D22E0583BDA3D8228D3DC + +0F8B2D8FCFD9D68CFFC17CCFB117709B53D26462A3F346FB7C79B85E:\ +47BE44B33C90FD2EC18B839C5A60175EB76DF0A8A587D6EF4A6712868CADBCC5\ +4AC88BE47987F7A4875C16C31B8A6D691939C007B6724139187E76413716F226 + +A963C3E895FF5A0BE4824400518D81412F875FA50521E26E85EAC90C04:\ +E0F91DA11320E76952D42C897503DDF79670C841DFD059AD40F41D9C5BAE0526\ +27887F5EF09A214AB6F2E5425AA1C634C29C533C596B1BE95B1D39EA06335694 + +03A18688B10CC0EDF83ADF0A84808A9718383C4070C6C4F295098699AC2C:\ +0CF4B313265173B60D2F99B87E81E76C10E855A0F67FD5F2D61216CAEF046A86\ +BC2B7E907412C5499A162BD1D019729653F2A80969A534776494A00C8193B8EE + +84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29:\ +B3483C99D6B488DC2E34F5024BBEE33B55D9A66B7EFE39657748650AC4301BA6\ +DC64A3E3E8C15945575DA963D29399BA0B1AC3A6CECF549E132A5E2DB3B5BBE7 + +9F2FCC7C90DE090D6B87CD7E9718C1EA6CB21118FC2D5DE9F97E5DB6AC1E9C10:\ +DA79A14B066580178121D3F60E0D3370F667A297FD9C0435CF8C65D35BB3B4AA\ +894AF7946F65CCAA5F7D9FC199CBCA9BE3FBFA958C0DABC992A50DB2236ED51C + +DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE0\ +46:\ +4A7873D42769DA269B9869E0DFD5695AE343DBD69FF8A68D93542B5EBBE79480\ +6B2D84ADC69DEAA58F54008164FB3E2AB02577865FBDEA88A8BE7D23EAA9441C + +62F154EC394D0BC757D045C798C8B87A00E0655D0481A7D2D9FB58D93AEDC676\ +B5A0:\ +CF42B5F7ABF540B69018484583A7B1CD1A38064C6E4208CE0ACEE27B7EE74CCE\ +C544FB2FA1921E95B5CACC12546D35C628ECA4C7053F37FD236E63346D474D00 + +B2DCFE9FF19E2B23CE7DA2A4207D3E5EC7C6112A8A22AEC9675A886378E14E5B\ +FBAD4E:\ +9F955DF8BAA1A5ECF0BDFD408002B1EAC93B89C8AEDFABB9E5239D6D1AD1C129\ +9901E96C822BE23207570E1EAE9CB82429899158313AF79FBB06EA3915436F7A + +47F5697AC8C31409C0868827347A613A3562041C633CF1F1F86865A576E02835\ +ED2C2492:\ +0FD1772A21CF32F0D43C00DF44754096704B0DBBC3B323500C3B231C7FC47B8F\ +35E8F10017F4B1061E82E5CC1D823014DCD54AD7F3588614E2149020CD8989B4 + +512A6D292E67ECB2FE486BFE92660953A75484FF4C4F2ECA2B0AF0EDCDD4339C\ +6B2EE4E542:\ +41D2D44C32A90B30ACE1C7F6E4AF5C3DC3ABDB1AC7365262C56CB1AE6DB6B5D4\ +2AD2BCFD9228D9DFFD5664756E326E9E88D053FD3A3D252211463B7171F5CB5C + +973CF2B4DCF0BFA872B41194CB05BB4E16760A1840D8343301802576197EC19E\ +2A1493D8F4FB:\ +4AF72DFCF27B0CDA02F35AAD1A90C67378B63523E80DD50A2AB512F2CFF2969F\ +A48DD8EDDE239F6BD5484D98FB26F0757831D7AFAAB5A21DBADB1C1B5BEA2336 + +80BEEBCD2E3F8A9451D4499961C9731AE667CDC24EA020CE3B9AA4BBC0A7F79E\ +30A934467DA4B0:\ +7161CDE092AE657F61BFA5957B5BADB16712A173EADEA014F622BA0CCF8B4BF9\ +E0E87B92032A5E1EF762FC7B734BD3B2AA526303C7EDE369885CE63DA6DD6DAE + +7ABAA12EC2A7347674E444140AE0FB659D08E1C66DECD8D6EAE925FA451D65F3\ +C0308E29446B8ED3:\ +52E566F481EBA7268B1C9440CCCC29EDFA7E03B4D5BE7689D9E6B9C0E097FC07\ +E378D7F189A144A31A7CA4280B3D566732C3DF2213A534B37D19A1AEFC332E90 + +C88DEE9927679B8AF422ABCBACF283B904FF31E1CAC58C7819809F65D5807D46\ +723B20F67BA610C2B7:\ +CFB6068414E7ABFBA715292306824859C4A8034964CC77C5DB1208FAED6274C3\ +7196850F81071E904BDA8CD1ECE8D66ACAB354EC5802846CA42A217941186AC3 + +01E43FE350FCEC450EC9B102053E6B5D56E09896E0DDD9074FE138E603821027\ +0C834CE6EADC2BB86BF6:\ +7CBE1D832F1530C7527FB3D8BB8F0BF7A2AF523A507EFE68AFDD1DCDE2852DD7\ +89AE87BA2DE8C6CE85AA0D6FD8EB2C4C0DC9E489A1D10105B56D4FFB1260EC0C + +337023370A48B62EE43546F17C4EF2BF8D7ECD1D49F90BAB604B839C2E6E5BD2\ +1540D29BA27AB8E309A4B7:\ +2B4F480C3799B7FF87DC0DBE2DC4348E2D42522EE803D89165002E8810734373\ +7B8605909795397DCA7442CD95799B91EAAB9993641F0578D4C86C7D01F564AD + +6892540F964C8C74BD2DB02C0AD884510CB38AFD4438AF31FC912756F3EFEC6B\ +32B58EBC38FC2A6B913596A8:\ +1556B21828CD8C1F98BFCC63415D4A4F9A916403EE0D65ACAB7AF2280FFA044F\ +5A0B773B7B6210C2D390A17464A791F52398264714FA89F990B03E810155BEF4 + +F5961DFD2B1FFFFDA4FFBF30560C165BFEDAB8CE0BE525845DEB8DC61004B7DB\ +38467205F5DCFB34A2ACFE96C0:\ +C17C6DD9964329D4F1AB10C57967E985A15EDF1DD3DEF79436198459A4D33136\ +7FADE1D20967BF3EAB50A8FBB892F0E71B0BAB981BB1D3EC64EBAB88447A66E9 + +CA061A2EB6CEED8881CE2057172D869D73A1951E63D57261384B80CEB5451E77\ +B06CF0F5A0EA15CA907EE1C27EBA:\ +81B3181C9610CA1EB3359A05329F597A7EFB663B86B413246C0755583B04B0D8\ +B266AD0343AD5813195DBFEDD031AE5CECE6DBA846803CB1C1787B838D66F295 + +1743A77251D69242750C4F1140532CD3C33F9B5CCDF7514E8584D4A5F9FBD730\ +BCF84D0D4726364B9BF95AB251D9BB:\ +48D1EBCCBCEE10E72A9AEE1785A2E97D0612BA7443152514A6F59A232F6D1A17\ +EC4415044A946DF2073FB1B979501B24ECE23C380EA1246C3F09B024C53D83EC + +D8FABA1F5194C4DB5F176FABFFF856924EF627A37CD08CF55608BBA8F1E324D7\ +C7F157298EABC4DCE7D89CE5162499F9:\ +6470A4A9540F4B9DEBBAECF5A95D05AFA9646FAC17B57944602F37740BBC3FA3\ +1C8F1D199013D15D4227209F89C333A493C4D83C8AEB186A9394619EDD1EB8DA + +BE9684BE70340860373C9C482BA517E899FC81BAAA12E5C6D7727975D1D41BA8\ +BEF788CDB5CF4606C9C1C7F61AED59F97D:\ +4446970CCDF75D54F79CCB3881A1ACA24D6CA8DEFBF0C248FD6E477223F2758B\ +9369B8140EE48BD0229B097F514E7A688506A890605C816714279105BEFDF112 + +7E15D2B9EA74CA60F66C8DFAB377D9198B7B16DEB6A1BA0EA3C7EE2042F89D37\ +86E779CF053C77785AA9E692F821F14A7F51:\ +4FEB1F07404D63A06BCDB2BCC319480CA02BEB7981972A092AF5C27001042EF6\ +3500955E57F5C3C54E0E964BD94ABC50BBAAC74F635E522D9ACF6740F26FC4CC + +9A219BE43713BD578015E9FDA66C0F2D83CAC563B776AB9F38F3E4F7EF229CB4\ +43304FBA401EFB2BDBD7ECE939102298651C86:\ +DE3F70F58116EF74466997946469929B5283B0289513AAF1F8DF770AEA21D9E1\ +308A5D1A30CF3912F4351BA6B1ADC4C2B35185C6479E5D160D678EE34BFC6CE5 + +C8F2B693BD0D75EF99CAEBDC22ADF4088A95A3542F637203E283BBC3268780E7\ +87D68D28CC3897452F6A22AA8573CCEBF245972A:\ +89C23F143C74B2A3EA4E1B52765B01CD38725DD432813816CFEDCDEF7090C01D\ +9964DAF8F0EEC99A23B20F1502CC8CB41F77CD35D1E1B1CCFFD96821525705E2 + +EC0F99711016C6A2A07AD80D16427506CE6F441059FD269442BAAA28C6CA037B\ +22EEAC49D5D894C0BF66219F2C08E9D0E8AB21DE52:\ +770FDA46E0435A36A9F4B9E81BB9945CD82F05ECCD6B46DAD48FF92825E2B4F5\ +D21608AE6B945AFAC4650F2408168D3538488FC20A8447FD01EC2DFDF55F8F36 + +0DC45181337CA32A8222FE7A3BF42FC9F89744259CFF653504D6051FE84B1A7F\ +FD20CB47D4696CE212A686BB9BE9A8AB1C697B6D6A33:\ +6FD2A68D85527B6A15F4E7499FF2C6028C74DE9CD2AD0837DFA4FDF64FEC3164\ +6BB89A80125F27D244718C635B5997D7CF014B5ED30A7CC5547C6C24C188B223 + +DE286BA4206E8B005714F80FB1CDFAEBDE91D29F84603E4A3EBC04686F99A46C\ +9E880B96C574825582E8812A26E5A857FFC6579F63742F:\ +0AE21935400D5DEFDB036321F900999BC9AFD61703510168190CC8D36D2BE4F4\ +9DE95C902C286DBAA91F516D231EC4D2AC55425D05FCDEDD211E67A3EFE51E12 + +EEBCC18057252CBF3F9C070F1A73213356D5D4BC19AC2A411EC8CDEEE7A571E2\ +E20EAF61FD0C33A0FFEB297DDB77A97F0A415347DB66BCAF:\ +24DCD83A82A389C7DCBDE997F9F1D0A52A64566699E5D8B8CDBFF0F88A427AAE\ +7C6BBB419F013B8CFC780D47101616BAF0B2C41CFDDD24BAF46610364FC82A03 + +416B5CDC9FE951BD361BD7ABFC120A5054758EBA88FDD68FD84E39D3B09AC254\ +97D36B43CBE7B85A6A3CEBDA8DB4E5549C3EE51BB6FCB6AC1E:\ +DD99BE3D8FB3C4A307E6ADFB18B638904CC12A033D61D1095DDFDC0F6FC62AE5\ +27CC5AF45084D2BE4A416E1BDED2E855650A9CEC6FE618B0856563FA1FDDFF38 + +5C5FAF66F32E0F8311C32E8DA8284A4ED60891A5A7E50FB2956B3CBAA79FC66C\ +A376460E100415401FC2B8518C64502F187EA14BFC9503759705:\ +359D189247A6B503F66FBA5CCE4BEBC7F6551239301BFCC608CFCCF8E9896305\ +5A6E6DD96F6813605B486403BB943A747EDE6C9F8AC586ED6E73DD4D4DC0296E + +7167E1E02BE1A7CA69D788666F823AE4EEF39271F3C26A5CF7CEE05BCA831610\ +66DC2E217B330DF821103799DF6D74810EED363ADC4AB99F36046A:\ +347E5762FA00809092ED5E660E399CF51EA861687AF8AD6D4EA50BE431764442\ +5000D1B33D9F3B05D7A961E2B385C4AF3ED5B5E767E4580C931747E5D3005CC8 + +2FDA311DBBA27321C5329510FAE6948F03210B76D43E7448D1689A063877B6D1\ +4C4F6D0EAA96C150051371F7DD8A4119F7DA5C483CC3E6723C01FB7D:\ +710B3E6D37198D55FE6DF676CF727F982E2B24E38456627D711E18C789AB9D99\ +6276C12F9605A567D1B7FA524296DB2E53D4DAC2F6089874CA099EBBB10E2071 + +95D1474A5AAB5D2422ACA6E481187833A6212BD2D0F91451A67DD786DFC91DFE\ +D51B35F47E1DEB8A8AB4B9CB67B70179CC26F553AE7B569969CE151B8D:\ +9E8D69EEDAEEE8F426D478B39693767D1B28CAC4CB47CD1416C73F82E29EBE06\ +2FBC41AD10A398F4EF4C124A70D96384EC5DBD2BE869DD84C9BA6808BAE6368F + +C71BD7941F41DF044A2927A8FF55B4B467C33D089F0988AA253D294ADDBDB325\ +30C0D4208B10D9959823F0C0F0734684006DF79F7099870F6BF53211A88D:\ +8F109A4B2F65CFC881CB456966630C91EF26E79838CF1E090488B9DC348FAD9F\ +F050197B373BA326AC5F42FD81F3D9C944238918E748453233EC309FA0000670 + +F57C64006D9EA761892E145C99DF1B24640883DA79D9ED5262859DCDA8C3C32E\ +05B03D984F1AB4A230242AB6B78D368DC5AAA1E6D3498D53371E84B0C1D4BA:\ +A94A8BBAAF30DA2D1BC52EFCE0541B8BD109663AD73830261B6179CA31D08CC5\ +ABF512CE3DE1118DE1230B31AFD5A01B5D6A49B370BEEE77A3988F9CBD32618C + +E926AE8B0AF6E53176DBFFCC2A6B88C6BD765F939D3D178A9BDE9EF3AA131C61\ +E31C1E42CDFAF4B4DCDE579A37E150EFBEF5555B4C1CB40439D835A724E2FAE7:\ +548D7A65D8BEEBE56C466DA17F8DD80722A7A2A59352465A150F58C1CDC75E80\ +49F5734EA16F32F5CE5B339CDFD99D930D20A6B8655B6F20DE4E7E7438C405E8 + +16E8B3D8F988E9BB04DE9C96F2627811C973CE4A5296B4772CA3EEFEB80A652B\ +DF21F50DF79F32DB23F9F73D393B2D57D9A0297F7A2F2E79CFDA39FA393DF1AC\ +00:\ +19152CBECBB159ED38D70436671A47CC9373EBC74EBB31FB22E36DD22E0DA921\ +15745AD7B1B0114596F940B6BC90C19EDD53A9AD012BF1F5B6B419FC8A1A6597 + +FC424EEB27C18A11C01F39C555D8B78A805B88DBA1DC2A42ED5E2C0EC737FF68\ +B2456D80EB85E11714FA3F8EABFB906D3C17964CB4F5E76B29C1765DB03D91BE\ +37FC:\ +F08612959457304C50026B146FAED6FEFE60EC27008F986130DE8D487C9BB29F\ +7A6A5F51F5083C6EEDBD2E9DE7A7B7658B8C10AD6F01807B4460FD3B36FC01BC + +ABE3472B54E72734BDBA7D9158736464251C4F21B33FBBC92D7FAC9A35C4E332\ +2FF01D2380CBAA4EF8FB07D21A2128B7B9F5B6D9F34E13F39C7FFC2E72E47888\ +599BA5:\ +436A9BAE3CA9FA4E8627C359D8D2628B0E2C341C75502B3EA80253E5448A6A52\ +4201DFABA2A2B42185DF0F94B06A8074216F057E300E16669A0271AE69B1A54C + +36F9F0A65F2CA498D739B944D6EFF3DA5EBBA57E7D9C41598A2B0E4380F3CF4B\ +479EC2348D015FFE6256273511154AFCF3B4B4BF09D6C4744FDD0F62D75079D4\ +40706B05:\ +BDDEB8D9A990C8B92FFD27D8B0EDA074D9F1DAF0E3FCA1F1D708D7B3922D5FB7\ +A92BD49523F74516CF373ECD835E399EF6E8ACFEB2C7A61166FA3FA9FEE0B5C7 + +ABC87763CAE1CA98BD8C5B82CABA54AC83286F87E9610128AE4DE68AC95DF5E3\ +29C360717BD349F26B872528492CA7C94C2C1E1EF56B74DBB65C2AC351981FDB\ +31D06C77A4:\ +76D74B7AA7C1787F7D2689144A9665416AABBA5B2646EC52C22F7DF5A20C7F6F\ +B2B1FD5C45668EDB0EE468A99567766F594D3E18F1D8162321445EF8F25A3D20 + +94F7CA8E1A54234C6D53CC734BB3D3150C8BA8C5F880EAB8D25FED13793A9701\ +EBE320509286FD8E422E931D99C98DA4DF7E70AE447BAB8CFFD92382D8A77760\ +A259FC4FBD72:\ +2D26A2CA37790EA1ED334F854CB6127F9D6EBBC716341A175B7C6625511974AB\ +1B6ADBC71014F258677089C2BB397F0669C34F686C008706E1DEB560B5D43DEE + +13BD2811F6ED2B6F04FF3895ACEED7BEF8DCD45EB121791BC194A0F806206BFF\ +C3B9281C2B308B1A729CE008119DD3066E9378ACDCC50A98A82E20738800B6CD\ +DBE5FE9694AD6D:\ +B28CF291DB775DEC4E87BD30792BC2CCF1B528F62537176C9206CF255F8B7959\ +10C65E3C308FA2275B021FFD737F88856107BDA44AEB4199EE5675471E789A81 + +1EED9CBA179A009EC2EC5508773DD305477CA117E6D569E66B5F64C6BC64801C\ +E25A8424CE4A26D575B8A6FB10EAD3FD1992EDDDEEC2EBE7150DC98F63ADC323\ +7EF57B91397AA8A7:\ +DABF7F4D5455F3C9505CA6B49CABD8ABD3EE4928CCEF88DC60FAAC08607CD686\ +1C316294D3954AA514672A289182C3FBE49B15051D4645214C5D01A6FC783899 + +BA5B67B5EC3A3FFAE2C19DD8176A2EF75C0CD903725D45C9CB7009A900C0B0CA\ +7A2967A95AE68269A6DBF8466C7B6844A1D608AC661F7EFF00538E323DB5F2C6\ +44B78B2D48DE1A08AA:\ +D4B8A36DE3B40CBCA69B5819C5D4E524E8C36FECAEB8092A5B02FFD12C19A17D\ +EA1B09F1430F1F62EB046CB0F7697233FB51E3EEFEA61CA2C320E97B34BA6ED8 + +0EFA26AC5673167DCACAB860932ED612F65FF49B80FA9AE65465E5542CB62075\ +DF1C5AE54FBA4DB807BE25B070033EFA223BDD5B1D3C94C6E1909C02B620D4B1\ +B3A6C9FED24D70749604:\ +61CD40E83B900F9730DE8BC331EA9F75F81D138992E500082FCFA41610BEEBBB\ +5ACE85FFF570462D9960D17A67A2D2BDC8CAD0D401DD642957386C553310CD42 + +BBFD933D1FD7BF594AC7F435277DC17D8D5A5B8E4D13D96D2F64E771ABBD51A5\ +A8AEA741BECCBDDB177BCEA05243EBD003CFDEAE877CCA4DA94605B67691919D\ +8B033F77D384CA01593C1B:\ +DBE49B8A74C886BA4B5E3E1FBF23274D8122019F7E66C61DB04CF5F61D75340D\ +34811558A575B179F2B45C7C7B60D3FDC1C5D9BB8F6DE53591AB9BC905702157 + +90078999FD3C35B8AFBF4066CBDE335891365F0FC75C1286CDD88FA51FAB94F9\ +B8DEF7C9AC582A5DBCD95817AFB7D1B48F63704E19C2BAA4DF347F48D4A6D603\ +013C23F1E9611D595EBAC37C:\ +826E66301DC5F89FA5559170A9AE0E07B1DCE27A5EB90029DC4E7C9A2F005D25\ +EE319DBD74A0F2D3034027ED03566F2D6D768A4F4BF88BF208AED0AD623D339E + +64105ECA863515C20E7CFBAA0A0B8809046164F374D691CDBD6508AAABC1819F\ +9AC84B52BAFC1B0FE7CDDBC554B608C01C8904C669D8DB316A0953A4C68ECE32\ +4EC5A49FFDB59A1BD6A292AA0E:\ +70FFCA06DC5C2ECC63E938915A70755843AE11990C4285FF4448D5DECCF9CF00\ +4C04774B6419E80D5E96CACF830F16595C995F37F629D4C82D7D5837AF28E6FA + +D4654BE288B9F3B711C2D02015978A8CC57471D5680A092AA534F7372C71CEAA\ +B725A383C4FCF4D8DEAA57FCA3CE056F312961ECCF9B86F14981BA5BED6AB5B4\ +498E1F6C82C6CAE6FC14845B3C8A:\ +E5C313F54B334BAB5746161EDBEA426AB1EE8FB01521C0BBE3B10B41F88498C0\ +A53D14D4F0951C0BEF8110ED3DBB4FE93CF0C538E7B4FC04D9D87FF98B690736 + +12D9394888305AC96E65F2BF0E1B18C29C90FE9D714DD59F651F52B88B3008C5\ +88435548066EA2FC4C101118C91F32556224A540DE6EFDDBCA296EF1FB00341F\ +5B01FECFC146BDB251B3BDAD556CD2:\ +40A3015076E0BD34B7A5EDDABE5C948A93C0C62C84470CD24EA4B624CADDB37A\ +FF2A9C654988231085A216F619697175F5AA2B6211C9E32D0FF4253EA95FD7D5 + +871A0D7A5F36C3DA1DFCE57ACD8AB8487C274FAD336BC137EBD6FF4658B547C1\ +DCFAB65F037AA58F35EF16AFF4ABE77BA61F65826F7BE681B5B6D5A1EA8085E2\ +AE9CD5CF0991878A311B549A6D6AF230:\ +F69BD0F7B6AEF0BA7FCA622865756298B881A4E747090C77F48B5BE74BA70DB2\ +2BDFAA758FF43698CA821472A121D46B3CDCFC62D139243B757A9456660843B4 + +E90B4FFEF4D457BC7711FF4AA72231CA25AF6B2E206F8BF859D8758B89A7CD36\ +105DB2538D06DA83BAD5F663BA11A5F6F61F236FD5F8D53C5E89F183A3CEC615\ +B50C7C681E773D109FF7491B5CC22296C5:\ +7DC20435E62DEA8C32FA4D6F90D16D711F4E43A14D74FA29F648EC2D0F0FD22E\ +10BF36220A639AC67AA2F5DFA0454565C9AF02A90F97F0202A1EBBEFB5859A1F + +E728DE62D75856500C4C77A428612CD804F30C3F10D36FB219C5CA0AA30726AB\ +190E5F3F279E0733D77E7267C17BE27D21650A9A4D1E32F649627638DBADA970\ +2C7CA303269ED14014B2F3CF8B894EAC8554:\ +9C7CFFFBFFE1E8783080510B7F9F11E04B3F9C5A6D17F5ACA02E07650347C352\ +A3CC60096FBCF21055385B0BA1EB3C6E4282690BFB32413FD55DE09E06403BE9 + +6348F229E7B1DF3B770C77544E5166E081850FA1C6C88169DB74C76E42EB983F\ +ACB276AD6A0D1FA7B50D3E3B6FCD799EC97470920A7ABED47D288FF883E24CA2\ +1C7F8016B93BB9B9E078BDB9703D2B781B616E:\ +A0E94AEB83183E924DEA9C94DE5F76EBDED8FB2D344C3CDF46FA8D738FF331EF\ +1061F96FD3D5D1F75EB95525B8388F4AB481D5BF9A48B9DE8E5DDE2F6C0B526B + +4B127FDE5DE733A1680C2790363627E63AC8A3F1B4707D982CAEA258655D9BF1\ +8F89AFE54127482BA01E08845594B671306A025C9A5C5B6F93B0A39522DC8774\ +37BE5C2436CBF300CE7AB6747934FCFC30AEAAF6:\ +FAC419F422D0A0C09653EB9938D6FEDA794CFE6162FEA02D35AD0C53F70CDFBF\ +5D60C4D33A5FAE394AC6938371A088977413172BC2284EA3C78623508726508C + +08461F006CFF4CC64B752C957287E5A0FAABC05C9BFF89D23FD902D324C79903\ +B48FCB8F8F4B01F3E4DDB483593D25F000386698F5ADE7FAADE9615FDC50D327\ +85EA51D49894E45BAA3DC707E224688C6408B68B11:\ +3722EE99604E8C8C7069FB1CC07B67F9DB082BE5BA359AC8FBBA285FFCC00204\ +39F96DFAD898124A779E758D3E8D28A41F3B59990C027F6E88D1FAD75112779D + +68C8F8849B120E6E0C9969A5866AF591A829B92F33CD9A4A3196957A148C4913\ +8E1E2F5C7619A6D5EDEBE995ACD81EC8BB9C7B9CFCA678D081EA9E25A75D39DB\ +04E18D475920CE828B94E72241F24DB72546B352A0E4:\ +BC30D45D62D909FC5ACD1B87B9C70065228D2722A360A1D25F726A8469F725FC\ +163496C39E7D31AA2B3BD9016A2253D7CD05E4D678A35358847090A778D8CF8D + +B8D56472954E31FB54E28FCA743F84D8DC34891CB564C64B08F7B71636DEBD64\ +CA1EDBDBA7FC5C3E40049CE982BBA8C7E0703034E331384695E9DE76B5104F2F\ +BC4535ECBEEBC33BC27F29F18F6F27E8023B0FBB6F563C:\ +E1DF1CF42A685BAD183FE9E7C3A21DF52826174DB659CA114E8EAE39569E5B20\ +EACF33A97ED436207F95568248FFBF922833A1D7153785FD869BAFC494ED82B1 + +0D58AC665FA84342E60CEFEE31B1A4EACDB092F122DFC68309077AED1F3E528F\ +578859EE9E4CEFB4A728E946324927B675CD4F4AC84F64DB3DACFE850C1DD187\ +44C74CECCD9FE4DC214085108F404EAB6D8F452B5442A47D:\ +B986BEA853B9CA92ED1F11D2205CDD09ACD3DD7DD4A4F48ADB1892F9B0296AB3\ +99B4CEDD69A6EC8C1E8E4FB30FD3040EB7057CDD3C0104EA910875196F93C53D + +1755E2D2E5D1C1B0156456B539753FF416651D44698E87002DCF61DCFA2B4E72\ +F264D9AD591DF1FDEE7B41B2EB00283C5AEBB3411323B672EAA145C512518510\ +4F20F335804B02325B6DEA65603F349F4D5D8B782DD3469CCD:\ +4DCE35639B8F219455E77AB4E0B99A94CB2DE19842D9213F11552EE9DD7A57E8\ +54EEB7E91F7E13152F757068E40105BB355306B3F16540991B11D215C02E8B80 + +B180DE1A611111EE7584BA2C4B020598CD574AC77E404E853D15A101C6F5A2E5\ +C801D7D85DC95286A1804C870BB9F00FD4DCB03AA8328275158819DCAD7253F3\ +E3D237AEAA7979268A5DB1C6CE08A9EC7C2579783C8AFC1F91A7:\ +E71B2170F0F3761D1FFF4C20A01374886E483724954F5F683120E4CDE589011C\ +7EAF775F3E0CD93953513DC0A119412E12611757F3BA846A33545FD257E5591B + +CF3583CBDFD4CBC17063B1E7D90B02F0E6E2EE05F99D77E24E560392535E47E0\ +5077157F96813544A17046914F9EFB64762A23CF7A49FE52A0A4C01C630CFE87\ +27B81FB99A89FF7CC11DCA5173057E0417B8FE7A9EFBA6D95C555F:\ +29036EEE2CFF84925CE84157EC3B90EDE0A434B52AD89C0F91E84D0F2CFD0357\ +1F610E18829B9B69984BB57FA055DE6288F43C33A9A19CF71B4045195B2908AD + +072FC02340EF99115BAD72F92C01E4C093B9599F6CFC45CB380EE686CB5EB019\ +E806AB9BD55E634AB10AA62A9510CC0672CD3EDDB589C7DF2B67FCD3329F61B1\ +A4441ECA87A33C8F55DA4FBBAD5CF2B2527B8E983BB31A2FADEC7523:\ +06E45A1A77F1CA437BB4554E9AC2791C74D7C3E7202D94C64C6ACF258FF7217A\ +46A8FCC49C6C9E56B53ADE741FA30060E35E365FFC9CD7BD3AEA92D011924D7E + +76EECF956A52649F877528146DE33DF249CD800E21830F65E90F0F25CA9D6540\ +FDE40603230ECA6760F1139C7F268DEBA2060631EEA92B1FFF05F93FD5572FBE\ +29579ECD48BC3A8D6C2EB4A6B26E38D6C5FBF2C08044AEEA470A8F2F26:\ +3A08CE7F48E71FB89CA12701C6BFB6D6ACBC3847351E0C4840CEC0FEEF141B69\ +A7780128837FA082E6803FCAC832DD57E5E8AA776B058ED5062AAEE0D3B10EA2 + +7ADC0B6693E61C269F278E6944A5A2D8300981E40022F839AC644387BFAC9086\ +650085C2CDC585FEA47B9D2E52D65A2B29A7DC370401EF5D60DD0D21F9E2B90F\ +AE919319B14B8C5565B0423CEFB827D5F1203302A9D01523498A4DB10374:\ +797015514DF48346879712ED2AD3BE484DB7F19B94DD8A4A77DA987287298674\ +F68E331432B15CFA0CEB395E40E2BD424B850293CD3BEE39B6F042B58469FE54 + +E1FFFA9826CCE8B86BCCEFB8794E48C46CDF372013F782ECED1E378269B7BE2B\ +7BF51374092261AE120E822BE685F2E7A83664BCFBE38FE8633F24E633FFE198\ +8E1BC5ACF59A587079A57A910BDA60060E85B5F5B6F776F0529639D9CCE4BD:\ +8930CF8606BF372E0F355E6036146EA14AC2F0605B2C192CCF3E60DEE5DD95C7\ +730581274AAF4DF61438051FF8A566B0A537E1ED13FF250F11EFD7F3257F9F60 + +69F9ABBA65592EE01DB4DCE52DBAB90B08FC04193602792EE4DAA263033D5908\ +1587B09BBE49D0B49C9825D22840B2FF5D9C5155F975F8F2C2E7A90C75D2E4A8\ +040FE39F63BBAFB403D9E28CC3B86E04E394A9C9E8065BD3C85FA9F0C7891600:\ +375AD74C0E39D401D4022174A5FA4363447C85D72ECCF1D380845149240DFD32\ +09F81E4AF263F429B8FB6116062880152AD9E40F01EC23B61E390EAB9AE3F502 + +38A10A352CA5AEDFA8E19C64787D8E9C3A75DBF3B8674BFAB29B5DBFC15A63D1\ +0FAE66CD1A6E6D2452D557967EAAD89A4C98449787B0B3164CA5B717A93F24EB\ +0B506CEB70CBBCB8D72B2A72993F909AAD92F044E0B5A2C9AC9CB16A0CA2F81F\ +49:\ +B0DD4E0619AAD0B8C44B30D106A0A57B8C10172520E072865B6CF5B12CFCA23A\ +F742AE9FE222C5D900C84BCE529C87F93BE4264331A7EDF7A1C0071F2265B1F5 + +6D8C6E449BC13634F115749C248C17CD148B72157A2C37BF8969EA83B4D6BA8C\ +0EE2711C28EE11495F43049596520CE436004B026B6C1F7292B9C436B055CBB7\ +2D530D860D1276A1502A5140E3C3F54A93663E4D20EDEC32D284E25564F62495\ +5B52:\ +4F70DF19FFAA4650A834B1BF154B61F077C76467F2EB38B3A60E26D82702294C\ +7E91611C63522D62B1EF007981516018833F9C7030BDA0A3661373F4739C8E94 + +6EFCBCAF451C129DBE00B9CEF0C3749D3EE9D41C7BD500ADE40CDC65DEDBBBAD\ +B885A5B14B32A0C0D087825201E303288A733842FA7E599C0C514E078F05C821\ +C7A4498B01C40032E9F1872A1C925FA17CE253E8935E4C3C71282242CB716B20\ +89CCC1:\ +24B8C31CA0EA5A1C627BBAEE4BA822323AC4198415FB69D99B90B26DAF42520E\ +6B489F05F9C48AF52BB7E11FC4D72C37CBFAA04433559EFC388CE9C83008C9F6 + +433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B982\ +14B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784444F\ +22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53E7E084\ +6DCBB4CE:\ +E1573F9C0D6D49D8A1D6B29663DB387A1EBB5F107C37A4E6330673B1A23DF7D1\ +B1475E14EA001319D683CD902CABA8E33B90A10FB7F1C5468E9A4FDBC7BFD2E1 + +A873E0C67CA639026B6683008F7AA6324D4979550E9BCE064CA1E1FB97A30B14\ +7A24F3F666C0A72D71348EDE701CF2D17E2253C34D1EC3B647DBCEF2F879F4EB\ +881C4830B791378C901EB725EA5C172316C6D606E0AF7DF4DF7F76E490CD30B2\ +BADF45685F:\ +669CAA7CE8599AF49B6AA8963FF4C19E43247953E0EAA7453EB954217AB9CA86\ +A82245E4C0916F7E9631F763A12B8EF516E5AB33DAC41D8FEB1F88B8778BF185 + +006917B64F9DCDF1D2D87C8A6173B64F6587168E80FAA80F82D84F60301E561E\ +312D9FBCE62F39A6FB476E01E925F26BCC91DE621449BE6504C504830AAE3940\ +96C8FC7694651051365D4EE9070101EC9B68086F2EA8F8AB7B811EA8AD934D5C\ +9B62C60A4771:\ +B0D673B7F25D73616323175F04CD969285914F163CDD0513CC97350C4BC50574\ +228BF1271026013A82260281554EAF29471F4CE3CC4472AA8030A6CF20982C32 + +F13C972C52CB3CC4A4DF28C97F2DF11CE089B815466BE88863243EB318C2ADB1\ +A417CB1041308598541720197B9B1CB5BA2318BD5574D1DF2174AF14884149BA\ +9B2F446D609DF240CE335599957B8EC80876D9A085AE084907BC5961B20BF5F6\ +CA58D5DAB38ADB:\ +61FE4777C89455B9FA259F9F8DEA012CBE1DC51538C54E77CE7D95EAC48E73F9\ +00B77B51B00018A6AF84C407877EE9B0DC3FF5788638A52AC8B150E823416640 + +E35780EB9799AD4C77535D4DDB683CF33EF367715327CF4C4A58ED9CBDCDD486\ +F669F80189D549A9364FA82A51A52654EC721BB3AAB95DCEB4A86A6AFA93826D\ +B923517E928F33E3FBA850D45660EF83B9876ACCAFA2A9987A254B137C6E140A\ +21691E1069413848:\ +2227BF50BD45C41592EB42EDAB9FEE3E78DD0FCF0497BFA733B99D9B5699D3A2\ +7932F4F81F7D4AF43A23E94CA7A9A88D82C2781602EF5E1ECF4712CE6F72E8F4 + +64EC021C9585E01FFE6D31BB50D44C79B6993D72678163DB474947A053674619\ +D158016ADB243F5C8D50AA92F50AB36E579FF2DABB780A2B529370DAA299207C\ +FBCDD3A9A25006D19C4F1FE33E4B1EAEC315D8C6EE1E730623FD1941875B924E\ +B57D6D0C2EDC4E78D6:\ +67F82DCA717D47E9E0854BEDC55A1756CD624F58DF755CF9702DE5CD73B57F6A\ +EF7BBF40922A915F383D7D3A910FF95936EC74E35B3B2AA6146F30E11AF3725B + +5954BAB512CF327D66B5D9F296180080402624AD7628506B555EEA8382562324\ +CF452FBA4A2130DE3E165D11831A270D9CB97CE8C2D32A96F50D71600BB4CA26\ +8CF98E90D6496B0A6619A5A8C63DB6D8A0634DFC6C7EC8EA9C006B6C456F1B20\ +CD19E781AF20454AC880:\ +83665C2BCA49C95BBE584DF52242068193F7A9DAAA67B0EE36FA9A81516E4CD6\ +A3D15A222F95A2DDB7494C5DBB7E83EB30A72BA342DC98060D1F78B9C8F0E893 + +03D9F92B2C565709A568724A0AFF90F8F347F43B02338F94A03ED32E6F33666F\ +F5802DA4C81BDCE0D0E86C04AFD4EDC2FC8B4141C2975B6F07639B1994C973D9\ +A9AFCE3D9D365862003498513BFA166D2629E314D97441667B007414E739D7FE\ +BF0FE3C32C17AA188A8683:\ +C505A3841C5589D0B2A428D684C9D14520C6359A5AAED6A560663947899E42B5\ +88D5D7BE55D580931B25AC2E2FC5F3AF360D60741C0BA82D5A94BE61D2CCC830 + +F31E8B4F9E0621D531D22A380BE5D9ABD56FAEC53CBD39B1FAB230EA67184440\ +E5B1D15457BD25F56204FA917FA48E669016CB48C1FFC1E1E45274B3B47379E0\ +0A43843CF8601A5551411EC12503E5AAC43D8676A1B2297EC7A0800DBFEE0429\ +2E937F21C005F17411473041:\ +EB6FD4B2B90F79F0071C8D2744C352DBDC7807D40EAF5979DBF21410CEFC2CA2\ +B867010A213C34090E3AFD0C8EA65F43D1AC48EAB67721AF5508D6F193031611 + +758EA3FEA738973DB0B8BE7E599BBEF4519373D6E6DCD7195EA885FC991D8967\ +62992759C2A09002912FB08E0CB5B76F49162AEB8CF87B172CF3AD190253DF61\ +2F77B1F0C532E3B5FC99C2D31F8F65011695A087A35EE4EEE5E334C369D8EE5D\ +29F695815D866DA99DF3F79403:\ +FF96DEEADD3C3668F9C9FCF23EABB6C08A908D89B997ED4005FDB4ADDFDBC165\ +D47CBDC2A9A064D95BEDDEDFE1F5AE0D7A05EED7D1B30D3DC1D3AC8850425575 + +47C6E0C2B74948465921868804F0F7BD50DD323583DC784F998A93CD1CA4C6EF\ +84D41DC81C2C40F34B5BEE6A93867B3BDBA0052C5F59E6F3657918C382E771D3\ +3109122CC8BB0E1E53C4E3D13B43CE44970F5E0C079D2AD7D7A3549CD75760C2\ +1BB15B447589E86E8D76B1E9CED2:\ +E0269128AD1687BB7C35926E98CC9A9C7670C1276C3F10C37853928AA6C0AE7F\ +E414D379FCBAE20DF0161781690053B9322D8AD14D66C1A4B7B35FFFF9CF3F16 + +F690A132AB46B28EDFA6479283D6444E371C6459108AFD9C35DBD235E0B6B6FF\ +4C4EA58E7554BD002460433B2164CA51E868F7947D7D7A0D792E4ABF0BE5F450\ +853CC40D85485B2B8857EA31B5EA6E4CCFA2F3A7EF3380066D7D8979FDAC618A\ +AD3D7E886DEA4F005AE4AD05E5065F:\ +CA5FA777561C6C13ECBCAD526527343009BB1EB77B4BCE263FC24E00A5A5FB92\ +96D2BA13598A646BF936397E43A7BF9D303CAE83E3654CC25F636F7FAB03C2B1 + +58D6A99BC6458824B256916770A8417040721CCCFD4B79EACD8B65A3767CE5BA\ +7E74104C985AC56B8CC9AEBD16FEBD4CDA5ADB130B0FF2329CC8D611EB14DAC2\ +68A2F9E633C99DE33997FEA41C52A7C5E1317D5B5DAED35EBA7D5A60E45D1FA7\ +EAABC35F5C2B0A0F2379231953322C4E:\ +FBCAE8C494C5FD0ADB640CEB4A15BF634293EC37CCF119AFF5BEC95F55578ED9\ +0D26861A045E0F242302158D3EAC801185498D6D8033662F2E0E6BA5B6F04ACE + +BEFAB574396D7F8B6705E2D5B58B2C1C820BB24E3F4BAE3E8FBCD36DBF734EE1\ +4E5D6AB972AEDD3540235466E825850EE4C512EA9795ABFD33F330D9FD7F79E6\ +2BBB63A6EA85DE15BEAEEA6F8D204A28956059E2632D11861DFB0E65BC07AC8A\ +159388D5C3277E227286F65FF5E5B5AEC1:\ +28500180D6F48671A4ACD83C9BB5FE3665CF9A6163D8797A2A2F9EA3974619B3\ +12769F67C1BB279A409C05A6B4E371F57FC658096923B5EB086D920EE8C748E8 + +8E58144FA9179D686478622CE450C748260C95D1BA43B8F9B59ABECA8D93488D\ +A73463EF40198B4D16FB0B0707201347E0506FF19D01BEA0F42B8AF9E71A1F1B\ +D168781069D4D338FDEF00BF419FBB003031DF671F4A37979564F69282DE9C65\ +407847DD0DA505AB1641C02DEA4F0D834986:\ +B205C2E223BF2A741F35294E9B7E1C33EF745A31F5CE2A00F6EC43B05044034C\ +4993D5112E4BA7CEB2BDA4C2E2C8E09B52CE6C2AC7B5374260BFEED8752B65C1 + +B55C10EAE0EC684C16D13463F29291BF26C82E2FA0422A99C71DB4AF14DD9C7F\ +33EDA52FD73D017CC0F2DBE734D831F0D820D06D5F89DACC485739144F8CFD47\ +99223B1AFF9031A105CB6A029BA71E6E5867D85A554991C38DF3C9EF8C1E1E9A\ +7630BE61CAABCA69280C399C1FB7A12D12AEFC:\ +38FA9FFE97CA84452F56C26702F561BBB105D1AE19D78C3528132DAA809B006E\ +E2359EFE54EB35FE0760699070D2B33B2401A5C12132797DF0BDAF96A8DDB04A + +2EEEA693F585F4ED6F6F8865BBAE47A6908AECD7C429E4BEC4F0DE1D0CA0183F\ +A201A0CB14A529B7D7AC0E6FF6607A3243EE9FB11BCF3E2304FE75FFCDDD6C5C\ +2E2A4CD45F63C962D010645058D36571404A6D2B4F44755434D76998E83409C3\ +205AA1615DB44057DB991231D2CB42624574F545:\ +F5D3FCDDF5C8E2E0513700B11775B0B3C73CD16B18AE52BD3ED225306EE9B5E6\ +B5E402334BC5A4FD1AF5D47138D44217DABF5CBDFFD6978B956EED71C21E05CF + +DAB11DC0B047DB0420A585F56C42D93175562852428499F66A0DB811FCDDDAB2\ +F7CDFFED1543E5FB72110B64686BC7B6887A538AD44C050F1E42631BC4EC8A9F\ +2A047163D822A38989EE4AAB01B4C1F161B062D873B1CFA388FD301514F62224\ +157B9BEF423C7783B7AAC8D30D65CD1BBA8D689C2D:\ +1A25D0833B2CC0A1A0D7C892639D0DF281D10334860F70878287DD4015A3F731\ +2093AEF197D49A1BE99F1615EA38D52A5F3665AA87BF20E89DD7A04E3DC09CA7 + +42E99A2F80AEE0E001279A2434F731E01D34A44B1A8101726921C0590C30F312\ +0EB83059F325E894A5AC959DCA71CE2214799916424E859D27D789437B9D2724\ +0BF8C35ADBAFCECC322B48AA205B293962D858652ABACBD588BCF6CBC388D099\ +3BD622F96ED54614C25B6A9AA527589EAAFFCF17DDF7:\ +0942326FEECAAD788EEB7D50863FD9280211C9F63B16ECD51AC874A80B47988D\ +61799A10D3B23DC23AE26C179ED5EBC9E32B7697B0566079852BBFA5FA21FFAC + +3C9B46450C0F2CAE8E3823F8BDB4277F31B744CE2EB17054BDDC6DFF36AF7F49\ +FB8A2320CC3BDF8E0A2EA29AD3A55DE1165D219ADEDDB5175253E2D1489E9B6F\ +DD02E2C3D3A4B54D60E3A47334C37913C5695378A669E9B72DEC32AF5434F93F\ +46176EBF044C4784467C700470D0C0B40C8A088C815816:\ +E9F908BC91CE95ABBA48644FC7C1F8E211E3D2EEA459021FF7E4496C6F1AA3EC\ +A73AEF2813B33819139CEB6ADD5FCFB4EBEBCE72AA1E30DC328454CA69FFBF31 + +D1E654B77CB155F5C77971A64DF9E5D34C26A3CAD6C7F6B300D39DEB19100946\ +91ADAA095BE4BA5D86690A976428635D5526F3E946F7DC3BD4DBC78999E65344\ +1187A81F9ADCD5A3C5F254BC8256B0158F54673DCC1232F6E918EBFC6C51CE67\ +EAEB042D9F57EEC4BFE910E169AF78B3DE48D137DF4F2840:\ +5CEEE2800816DDF676BBD3C8B7D95012808E62A1838CD292893B05085DD08B95\ +EA245FB84283BEF479FD0E2B8BF9DD1BA722344E83DC391A85AEE2C930F985C5 + +626F68C18A69A6590159A9C46BE03D5965698F2DAC3DE779B878B3D9C421E0F2\ +1B955A16C715C1EC1E22CE3EB645B8B4F263F60660EA3028981EEBD6C8C3A367\ +285B691C8EE56944A7CD1217997E1D9C21620B536BDBD5DE8925FF71DEC6FBC0\ +6624AB6B21E329813DE90D1E572DFB89A18120C3F606355D25:\ +ED0C620D495F5190D8667F0F9B50C9FEA28FC01AE9B219027973A341BA87118A\ +821451D5EEE580C4FAEE46DAD21C43C72523AE86A8579576247EB8E38D0C6BA6 + +651A6FB3C4B80C7C68C6011675E6094EB56ABF5FC3057324EBC6477825061F9F\ +27E7A94633ABD1FA598A746E4A577CAF524C52EC1788471F92B8C37F23795CA1\ +9D559D446CAB16CBCDCE90B79FA1026CEE77BF4AB1B503C5B94C2256AD75B3EA\ +C6FD5DCB96ACA4B03A834BFB4E9AF988CECBF2AE597CB9097940:\ +138F2DF9686F705E5C55020B89F04AB66654B0CACCC1A8D374334B6BF6534335\ +C7514206B6F772DDB0550CFABA22D22B913928D3ADF78BFD25DF9DD517B2E3A3 + +8AAF072FCE8A2D96BC10B3C91C809EE93072FB205CA7F10ABD82ECD82CF040B1\ +BC49EA13D1857815C0E99781DE3ADBB5443CE1C897E55188CEAF221AA9681638\ +DE05AE1B322938F46BCE51543B57ECDB4C266272259D1798DE13BE90E10EFEC2\ +D07484D9B21A3870E2AA9E06C21AA2D0C9CF420080A80A91DEE16F:\ +3348F4E8C4768C3EF687A8E2A02E307FD8591B41235F8C14E5983AE7361968D0\ +CB877AF488B975001AA1E7ACF0E5844C107A102BF028FCEE89CFE751266D88A3 + +53F918FD00B1701BD504F8CDEA803ACCA21AC18C564AB90C2A17DA592C7D6968\ +8F6580575395551E8CD33E0FEF08CA6ED4588D4D140B3E44C032355DF1C53156\ +4D7F4835753344345A6781E11CD5E095B73DF5F82C8AE3AD00877936896671E9\ +47CC52E2B29DCD463D90A0C9929128DA222B5A211450BBC0E02448E2:\ +CA7257AC51700539DF617C3B7EE9ACC7C4576332996F905D9D3733F1AAF3287E\ +2F852BE394E533F64EA19733276B0E448496F88500770675835E133904E4071B + +A64599B8A61B5CCEC9E67AED69447459C8DA3D1EC6C7C7C82A7428B9B584FA67\ +E90F68E2C00FBBED4613666E5168DA4A16F395F7A3C3832B3B134BFC9CBAA95D\ +2A0FE252F44AC6681EB6D40AB91C1D0282FED6701C57463D3C5F2BB8C6A7301F\ +B4576AA3B5F15510DB8956FF77478C26A7C09BEA7B398CFC83503F538E:\ +ADB3B6E2083CB37ED5F822D1AA2ADA18560C663011CB16CFB804A5F24C0525F3\ +4D8CB10D19528BA02BB43BD501BF0D0AC67968B0687DCB21C013527A99AE9D84 + +0E3AB0E054739B00CDB6A87BD12CAE024B54CB5E550E6C425360C2E87E59401F\ +5EC24EF0314855F0F56C47695D56A7FB1417693AF2A1ED5291F2FEE95F75EED5\ +4A1B1C2E81226FBFF6F63ADE584911C71967A8EB70933BC3F5D15BC91B5C2644\ +D9516D3C3A8C154EE48E118BD1442C043C7A0DBA5AC5B1D5360AAE5B9065:\ +EA781FDD2DDDE4B42E1A6B75AB70CFCF17DC413CD9591254F91F1E9741811916\ +56EDC92823A3145DBE4AB491E86233DAACD748CCD2A86B551D6D47EDEA943C82 + +A62FC595B4096E6336E53FCDFC8D1CC175D71DAC9D750A6133D23199EAAC2882\ +07944CEA6B16D27631915B4619F743DA2E30A0C00BBDB1BBB35AB852EF3B9AEC\ +6B0A8DCC6E9E1ABAA3AD62AC0A6C5DE765DE2C3711B769E3FDE44A74016FFF82\ +AC46FA8F1797D3B2A726B696E3DEA5530439ACEE3A45C2A51BC32DD055650B:\ +B2DCDDF444C51976F2D71D020BEF76810C8CCAE2B94C34178C600CCDD04B233B\ +A2D27DB4E8F07EE01D611E490564B6071858BC8B8F8D23BC6B8DA746DAD4A132 + +2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C141\ +29BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CA\ +E275234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF281\ +98E3732501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817:\ +447C299F7E5C90CEE70A7577EC148FEF194F40BA7C3C8CBC96FF81D14490A16E\ +397CA01F3C0883E050F805239FBD4189122B45B1101EE1F303281D2AC1580E2C + +10DB509B2CDCABA6C062AE33BE48116A29EB18E390E1BBADA5CA0A2718AFBCD2\ +3431440106594893043CC7F2625281BF7DE2655880966A23705F0C5155C2F5CC\ +A9F2C2142E96D0A2E763B70686CD421B5DB812DACED0C6D65035FDE558E94F26\ +B3E6DDE5BD13980CC80292B723013BD033284584BFF27657871B0CF07A849F4A\ +E2:\ +E21AEB7109CA41F1C41F4B66E80A6A4248AED43341F1EFFABB61341C3F0B6355\ +EFE3DAA8D28D60F9BF851E6837625BF2EBFD8A68CDCB50718660D5CCBFD93910 + +9334DE60C997BDA6086101A6314F64E4458F5FF9450C509DF006E8C547983C65\ +1CA97879175AABA0C539E82D05C1E02C480975CBB30118121061B1EBAC4F8D9A\ +3781E2DB6B18042E01ECF9017A64A0E57447EC7FCBE6A7F82585F7403EE2223D\ +52D37B4BF426428613D6B4257980972A0ACAB508A7620C1CB28EB4E9D30FC413\ +61EC:\ +FC015B69F1AE0DC7004343FF941378B8A23AA45A3825310E9A81C2A9EA2D4F96\ +1F4C9B8CACBC91F0D2414590C389D24ED482B95252F37B5A6CC6BFAEA5C98C32 + +E88AB086891693AA535CEB20E64C7AB97C7DD3548F3786339897A5F0C3903154\ +9CA870166E477743CCFBE016B4428D89738E426F5FFE81626137F17AECFF61B7\ +2DBEE2DC20961880CFE281DFAB5EE38B1921881450E16032DE5E4D55AD8D4FCA\ +609721B0692BAC79BE5A06E177FE8C80C0C83519FB3347DE9F43D5561CB8107B\ +9B5EDC:\ +45CCB97F9524BA87A7E69354030C71A07D875C5E958EA167EFF581703B1D5037\ +BD91B8806980E3D4EAE0ACB010D210CD89F781DED33F5697DAC285AEB37629A4 + +FD19E01A83EB6EC810B94582CB8FBFA2FCB992B53684FB748D2264F020D3B960\ +CB1D6B8C348C2B54A9FCEA72330C2AAA9A24ECDB00C436ABC702361A82BB8828\ +B85369B8C72ECE0082FE06557163899C2A0EFA466C33C04343A839417057399A\ +63A3929BE1EE4805D6CE3E5D0D0967FE9004696A5663F4CAC9179006A2CEB755\ +42D75D68:\ +142922E983887BFF20D0EE26BCBCBA34A1A70717172B8FBDE0AEABC5CA258C39\ +85B00F7908A21A75C014D4B2542A1BFCB7469BA9454F66670B6C05BBBD7A92D3 + +59AE20B6F7E0B3C7A989AFB28324A40FCA25D8651CF1F46AE383EF6D8441587A\ +A1C04C3E3BF88E8131CE6145CFB8973D961E8432B202FA5AF3E09D625FAAD825\ +BC19DA9B5C6C20D02ABDA2FCC58B5BD3FE507BF201263F30543819510C12BC23\ +E2DDB4F711D087A86EDB1B355313363A2DE996B891025E147036087401CCF3CA\ +7815BF3C49:\ +41DF07681C94633DC430AD7FFF9AB7146F1CC3A66DF3A81D990ED3D247D8F9A5\ +880EFF20C2652FB6C6631EA41F54D6C331651FDC20783EED65B83AF458D0AC72 + +77EE804B9F3295AB2362798B72B0A1B2D3291DCEB8139896355830F34B3B3285\ +61531F8079B79A6E9980705150866402FDC176C05897E359A6CB1A7AB067383E\ +B497182A7E5AEF7038E4C96D133B2782917417E391535B5E1B51F47D8ED7E4D4\ +025FE98DC87B9C1622614BFF3D1029E68E372DE719803857CA52067CDDAAD958\ +951CB2068CC6:\ +9BEE78530C0A93CE8564AEDE785D7086CE066CB74C3B8F70D3851CD57DB8E647\ +E67DF0D543EAFEDED491613BD3268CC7CE8DE34614A79D6413C3FEE218B6965A + +B771D5CEF5D1A41A93D15643D7181D2A2EF0A8E84D91812F20ED21F147BEF732\ +BF3A60EF4067C3734B85BC8CD471780F10DC9E8291B58339A677B960218F71E7\ +93F2797AEA349406512829065D37BB55EA796FA4F56FD8896B49B2CD19B43215\ +AD967C712B24E5032D065232E02C127409D2ED4146B9D75D763D52DB98D949D3\ +B0FED6A8052FBB:\ +E2548952816803ED478241CBAB10F69DB4CBDD98447BFAF4E92AF9A3179B6EFA\ +CEC56C757944B519C69D1759811732FE3C52912611271231342D9D62F3472967 + +B32D95B0B9AAD2A8816DE6D06D1F86008505BD8C14124F6E9A163B5A2ADE55F8\ +35D0EC3880EF50700D3B25E42CC0AF050CCD1BE5E555B23087E04D7BF9813622\ +780C7313A1954F8740B6EE2D3F71F768DD417F520482BD3A08D4F222B4EE9DBD\ +015447B33507DD50F3AB4247C5DE9A8ABD62A8DECEA01E3B87C8B927F5B08BEB\ +37674C6F8E380C04:\ +0E673628FA620668F73E652DF7927EC7D9DF9426F157B055E39D23AD7FA9CCCD\ +C8013FB8F6A0D2EFFEBE00BB5563B100B5361F33808AE20E23580D414F909CED + +04410E31082A47584B406F051398A6ABE74E4DA59BB6F85E6B49E8A1F7F2CA00\ +DFBA5462C2CD2BFDE8B64FB21D70C083F11318B56A52D03B81CAC5EEC29EB31B\ +D0078B6156786DA3D6D8C33098C5C47BB67AC64DB14165AF65B44544D806DDE5\ +F487D5373C7F9792C299E9686B7E5821E7C8E2458315B996B5677D926DAC57B3\ +F22DA873C601016A0D:\ +1B0E41061FF47E71F22FCD508E8560F8E4C9748DD8E520A9CA478F3E3827330C\ +6F19E299E221367E6B02E1606A1B23F2B3F66762D0F408B3A68C9DA9018A45DD + +8B81E9BADDE026F14D95C019977024C9E13DB7A5CD21F9E9FC491D716164BBAC\ +DC7060D882615D411438AEA056C340CDF977788F6E17D118DE55026855F93270\ +472D1FD18B9E7E812BAE107E0DFDE7063301B71F6CFE4E225CAB3B232905A56E\ +994F08EE2891BA922D49C3DAFEB75F7C69750CB67D822C96176C46BD8A29F170\ +1373FB09A1A6E3C7158F:\ +FEE0EA0269154ADD8FCC28BC61D290CCE0CA04FEBD3EF646D5AEED6542461D4C\ +DA983932BE7ABF3E0C2639ACF75AE2770D1B511D996E19536542FB4D76505F69 + +FA6EED24DA6666A22208146B19A532C2EC9BA94F09F1DEF1E7FC13C399A48E41\ +ACC2A589D099276296348F396253B57CB0E40291BD282773656B6E0D8BEA1CDA\ +084A3738816A840485FCF3FB307F777FA5FEAC48695C2AF4769720258C77943F\ +B4556C362D9CBA8BF103AEB9034BAA8EA8BFB9C4F8E6742CE0D52C49EA8E974F\ +339612E830E9E7A9C29065:\ +82DFF74AC5CDFFA0D1D03049F2FC227DCB77E373381C2E74FA316BBF9F6D55AE\ +B7667A95AE4D4D367130620217E245E9DDC641AFF823475AE40E4E3CE56FCD40 + +9BB4AF1B4F09C071CE3CAFA92E4EB73CE8A6F5D82A85733440368DEE4EB1CBC7\ +B55AC150773B6FE47DBE036C45582ED67E23F4C74585DAB509DF1B8361056454\ +5642B2B1EC463E18048FC23477C6B2AA035594ECD33791AF6AF4CBC2A1166ABA\ +8D628C57E707F0B0E8707CAF91CD44BDB915E0296E0190D56D33D8DDE10B5B60\ +377838973C1D943C22ED335E:\ +97D7C677B7D8EA600DE069CC23C492C0C293EB8E9B8987978CD43B2CACE445A9\ +0D1CDFA4E0F347EC9B7E6394DEF55702A13DC5DE3C5E43B8B08F260BF0E654D5 + +2167F02118CC62043E9091A647CADBED95611A521FE0D64E8518F16C808AB297\ +725598AE296880A773607A798F7C3CFCE80D251EBEC6885015F9ABF7EAABAE46\ +798F82CB5926DE5C23F44A3F9F9534B3C6F405B5364C2F8A8BDC5CA49C749BED\ +8CE4BA48897062AE8424CA6DDE5F55C0E42A95D1E292CA54FB46A84FBC9CD87F\ +2D0C9E7448DE3043AE22FDD229:\ +A0A9203714A9DCAE2402958E6BCF759B7E900D13D5A8654501ADAC70B5CEDF27\ +D21F5E92219DAD31DDC8466D8F559470C638D9F9B45D4F539D36C54651C4852C + +94B7FA0BC1C44E949B1D7617D31B4720CBE7CA57C6FA4F4094D4761567E389EC\ +C64F6968E4064DF70DF836A47D0C713336B5028B35930D29EB7A7F9A5AF9AD5C\ +F441745BAEC9BB014CEEFF5A41BA5C1CE085FEB980BAB9CF79F2158E03EF7E63\ +E29C38D7816A84D4F71E0F548B7FC316085AE38A060FF9B8DEC36F91AD9EBC0A\ +5B6C338CBB8F6659D342A24368CF:\ +E6D9B97F5BDB0BB4F5D2322CEFF8A1A747361BB937BCFA69EB8C23D98BEA5C5E\ +E25F9587648912D5E7F90E73C031A27E27FB11276CCB63E47C25B18649AE5DD8 + +EA40E83CB18B3A242C1ECC6CCD0B7853A439DAB2C569CFC6DC38A19F5C90ACBF\ +76AEF9EA3742FF3B54EF7D36EB7CE4FF1C9AB3BC119CFF6BE93C03E208783335\ +C0AB8137BE5B10CDC66FF3F89A1BDDC6A1EED74F504CBE7290690BB295A872B9\ +E3FE2CEE9E6C67C41DB8EFD7D863CF10F840FE618E7936DA3DCA5CA6DF933F24\ +F6954BA0801A1294CD8D7E66DFAFEC:\ +0A14506B804455218133711A3BA8307615E4F80A5334B86555B9CEC77C93450A\ +92F6A18BED9BD55B1848F78C2A49A76057FCF3509663F2E9010C39D94FC9918C + +157D5B7E4507F66D9A267476D33831E7BB768D4D04CC3438DA12F9010263EA5F\ +CAFBDE2579DB2F6B58F911D593D5F79FB05FE3596E3FA80FF2F761D1B0E57080\ +055C118C53E53CDB63055261D7C9B2B39BD90ACC32520CBBDBDA2C4FD8856DBC\ +EE173132A2679198DAF83007A9B5C51511AE49766C792A29520388444EBEFE28\ +256FB33D4260439CBA73A9479EE00C63:\ +8D03AFCB3940007FCBCEEB023C105918E6540D87658E59109CC6568CF804BD3F\ +A2B3968C28C650E55276218482BB8E42944272673D6A137D326477A1BAFE8F3D + +836B34B515476F613FE447A4E0C3F3B8F20910AC89A3977055C960D2D5D2B72B\ +D8ACC715A9035321B86703A411DDE0466D58A59769672AA60AD587B8481DE4BB\ +A552A1645779789501EC53D540B904821F32B0BD1855B04E4848F9F8CFE9EBD8\ +911BE95781A759D7AD9724A7102DBE576776B7C632BC39B9B5E19057E226552A\ +5994C1DBB3B5C7871A11F5537011044C53:\ +4862476DDDADDCDE60A35260AB6C448B9B6DAD7ED296FC48B81E288D0E397E69\ +4535CC8999F4D7F2F3E09F5CE034DB0F71EF5C812F3C6BBD73FBEF14B252BC55 + +CC7784A4912A7AB5AD3620AAB29BA87077CD3CB83636ADC9F3DC94F51EDF521B\ +2161EF108F21A0A298557981C0E53CE6CED45BDF782C1EF200D29BAB81DD6460\ +586964EDAB7CEBDBBEC75FD7925060F7DA2B853B2B089588FA0F8C16EC6498B1\ +4C55DCEE335CB3A91D698E4D393AB8E8EAC0825F8ADEBEEE196DF41205C01167\ +4E53426CAA453F8DE1CBB57932B0B741D4C6:\ +4B239C5B1C8B83924AE736E9D30582D16BF00A547023244247B389259BC62649\ +81606439AC9DDE0A7D371B73A34CAC998823803D7BD62ABF8905C9BD550EBAB8 + +7639B461FFF270B2455AC1D1AFCE782944AEA5E9087EB4A39EB96BB5C3BAAF0E\ +868C8526D3404F9405E79E77BFAC5FFB89BF1957B523E17D341D7323C302EA70\ +83872DD5E8705694ACDDA36D5A1B895AAA16ECA6104C82688532C8BFE1790B5D\ +C9F4EC5FE95BAED37E1D287BE710431F1E5E8EE105BC42ED37D74B1E55984BF1\ +C09FE6A1FA13EF3B96FAEAED6A2A1950A12153:\ +2B0D1C2780D8826CCE4B71A77C9833AE59C2BD0213789A8892CCD7B4FFF1D8A7\ +80E81AD4C2C1228D55DF5BA3625DE4860DB05743E4D07934C434BAD5A769131B + +EB6513FC61B30CFBA58D4D7E80F94D14589090CF1D80B1DF2E68088DC6104959\ +BA0D583D585E9578AB0AEC0CF36C48435EB52ED9AB4BBCE7A5ABE679C97AE2DB\ +E35E8CC1D45B06DDA3CF418665C57CBEE4BBB47FA4CAF78F4EE656FEC237FE4E\ +EBBAFA206E1EF2BD0EE4AE71BD0E9B2F54F91DAADF1FEBFD7032381D636B733D\ +CB3BF76FB14E23AFF1F68ED3DBCF75C9B99C6F26:\ +0880376CD5FFC7EBCC6E80FAE0D78DBB3532500BAB96CD4B755584D23E68CF59\ +F5297A34AE0A90184773412BC9548A80E4C54391B4CB59CE292D704C614DD1A1 + +1594D74BF5DDE444265D4C04DAD9721FF3E34CBF622DAF341FE16B96431F6C4D\ +F1F760D34F296EB97D98D560AD5286FEC4DCE1724F20B54FD7DF51D4BF137ADD\ +656C80546FB1BF516D62EE82BAA992910EF4CC18B70F3F8698276FCFB44E0EC5\ +46C2C39CFD8EE91034FF9303058B4252462F86C823EB15BF481E6B79CC3A0221\ +8595B3658E8B37382BD5048EAED5FD02C37944E73B:\ +E725B8C82C8D1F3963A77D505B0A929FD58846061BEA2BA7040B7D3B2AD95EE3\ +781CACA60B372EB5258A44A65BB9EE655A1EF9102F8BBD9E41FCFB2871DAEC7D + +4CFA1278903026F66FEDD41374558BE1B585D03C5C55DAC94361DF286D4BD39C\ +7CB8037ED3B267B07C346626449D0CC5B0DD2CF221F7E4C3449A4BE99985D2D5\ +E67BFF2923357DDEAB5ABCB4619F3A3A57B2CF928A022EB27676C6CF80568900\ +4FCA4D41EA6C2D0A4789C7605F7BB838DD883B3AD3E6027E775BCF2628814280\ +99C7FFF95B14C095EA130E0B9938A5E22FC52650F591:\ +31175C65FF1133F5F53DB80DEB90F6B2E79727D4C8E77C5E3F5DEF70525B871B\ +50249C6F2EE1CA6F11A7CD9C578CF13D5FCBD74DE1D05AF6076A5459E10B4B9D + +D3E65CB92CFA79662F6AF493D696A07CCF32AAADCCEFF06E73E8D9F6F909209E\ +66715D6E978788C49EFB9087B170ECF3AA86D2D4D1A065AE0EFC8924F365D676\ +B3CB9E2BEC918FD96D0B43DEE83727C9A93BF56CA2B2E59ADBA85696546A8150\ +67FC7A78039629D4948D157E7B0D826D1BF8E81237BAB7321312FDAA4D521744\ +F988DB6FDF04549D0FDCA393D639C729AF716E9C8BBA48:\ +870B40EE6B774B732E15DEE647F75BF3D5DD6FD364C7E1BB184D8AC1F0C991E2\ +486DCE6BD6CEFA1DFFE13C50260D4A0FB6C23E29D7E62CFF0F8DE785CA53C2A2 + +842CC583504539622D7F71E7E31863A2B885C56A0BA62DB4C2A3F2FD12E79660\ +DC7205CA29A0DC0A87DB4DC62EE47A41DB36B9DDB3293B9AC4BAAE7DF5C6E720\ +1E17F717AB56E12CAD476BE49608AD2D50309E7D48D2D8DE4FA58AC3CFEAFEEE\ +48C0A9EEC88498E3EFC51F54D300D828DDDCCB9D0B06DD021A29CF5CB5B25069\ +15BEB8A11998B8B886E0F9B7A80E97D91A7D01270F9A7717:\ +8FDE68D448144F3B4BD12011DF94A463C40BE946821F80EC8197E36EB46554F7\ +AD8B6CA9F6FCC8C05B3C0C2C909966AACBA2A1AA6E980E57AEA1CB35B01DC991 + +6C4B0A0719573E57248661E98FEBE326571F9A1CA813D3638531AE28B4860F23\ +C3A3A8AC1C250034A660E2D71E16D3ACC4BF9CE215C6F15B1C0FC7E77D3D2715\ +7E66DA9CEEC9258F8F2BF9E02B4AC93793DD6E29E307EDE3695A0DF63CBDC0FC\ +66FB770813EB149CA2A916911BEE4902C47C7802E69E405FE3C04CEB5522792A\ +5503FA829F707272226621F7C488A7698C0D69AA561BE9F378:\ +F19E37E56DE97B6EF009CB1B0A8FEB42891DE80A9895C7413367C71FF34815F9\ +77A053FD621C30738C347262DF2B07EC3E455DC729803FA3D68BFBFF42415500 + +51B7DBB7CE2FFEB427A91CCFE5218FD40F9E0B7E24756D4C47CD55606008BDC2\ +7D16400933906FD9F30EFFDD4880022D081155342AF3FB6CD53672AB7FB5B3A3\ +BCBE47BE1FD3A2278CAE8A5FD61C1433F7D350675DD21803746CADCA574130F0\ +1200024C6340AB0CC2CF74F2234669F34E9009EF2EB94823D62B31407F4BA46F\ +1A1EEC41641E84D77727B59E746B8A671BEF936F05BE820759FA:\ +BC3199569054F2DBDC66744F3B6B7DC23D3708BCD96A8C7B7C5D9E58087E2E4A\ +5D5606CEF88AD63044C9A4F0D019358846EE83FE98CFE9C5B03B29A2D31B3134 + +83599D93F5561E821BD01A472386BC2FF4EFBD4AED60D5821E84AAE74D807102\ +9810F5E286F8F17651CD27DA07B1EB4382F754CD1C95268783AD09220F550284\ +0370D494BEB17124220F6AFCE91EC8A0F55231F9652433E5CE3489B727716CF4\ +AEBA7DCDA20CD29AA9A859201253F948DD94395ABA9E3852BD1D60DDA7AE5DC0\ +45B283DA006E1CBAD83CC13292A315DB5553305C628DD091146597:\ +C44780E409877812578CF0D738A6394B1EBF7183941323C2891D9604B93E5748\ +EAB2FD4732DCE6D9A5D1F27B7FADFD5DFDC87264BE97F86F700AE87A5D1B8227 + +2BE9BF526C9D5A75D565DD11EF63B979D068659C7F026C08BEA4AF161D85A462\ +D80E45040E91F4165C074C43AC661380311A8CBED59CC8E4C4518E80CD2C78AB\ +1CABF66BFF83EAB3A80148550307310950D034A6286C93A1ECE8929E6385C5E3\ +BB6EA8A7C0FB6D6332E320E71CC4EB462A2A62E2BFE08F0CCAD93E61BEDB5DD0\ +B786A728AB666F07E0576D189C92BF9FB20DCA49AC2D3956D47385E2:\ +98474C61C2639BA15B58D98429F0E3489504CC6ED3BF638ACCF6859443AF2BCB\ +F85EDBEF50191EDB6923636B21C2E76E985831F187575BA82E9AB4CA40CC482F + +CA76D3A12595A817682617006848675547D3E8F50C2210F9AF906C0E7CE50B44\ +60186FE70457A9E879E79FD4D1A688C70A347361C847BA0DD6AA52936EAF8E58\ +A1BE2F5C1C704E20146D366AEB3853BED9DE9BEFE9569AC8AAEA37A9FB7139A1\ +A1A7D5C748605A8DEFB297869EBEDD71D615A5DA23496D11E11ABBB126B206FA\ +0A7797EE7DE117986012D0362DCEF775C2FE145ADA6BDA1CCB326BF644:\ +F94556B89FA106C94D32F723061D2E88EBC4164B1B02D0485851782F84CC3229\ +7D7A3AF9A1CC430702B78B5BDC9E50ABDD703201AA73F8811AEB4A80A5992C64 + +F76B85DC67421025D64E93096D1D712B7BAF7FB001716F02D33B2160C2C882C3\ +10EF13A576B1C2D30EF8F78EF8D2F465007109AAD93F74CB9E7D7BEF7C9590E8\ +AF3B267C89C15DB238138C45833C98CC4A471A7802723EF4C744A853CF80A0C2\ +568DD4ED58A2C9644806F42104CEE53628E5BDF7B63B0B338E931E31B87C24B1\ +46C6D040605567CEEF5960DF9E022CB469D4C787F4CBA3C544A1AC91F95F:\ +60440509E00573D66609563D8F1504A196AF06D46F6CDBFEEAFF61FE46AD0845\ +6EE24BCA13DDED11818776CAC19376AE7415338A3D4F0035FF276188BF11420F + +25B8C9C032EA6BCD733FFC8718FBB2A503A4EA8F71DEA1176189F694304F0FF6\ +8E862A8197B839957549EF243A5279FC2646BD4C009B6D1EDEBF24738197ABB4\ +C992F6B1DC9BA891F570879ACCD5A6B18691A93C7D0A8D38F95B639C1DAEB48C\ +4C2F15CCF5B9D508F8333C32DE78781B41850F261B855C4BEBCC125A380C54D5\ +01C5D3BD07E6B52102116088E53D76583B0161E2A58D0778F091206AABD5A1:\ +2D552519EC54E5BBBFDBB543EAE5482D9B964A952E880A88567E7DDF1DCD0D5A\ +A353F7BE15D7634ADBDBEFA85355839FDA2B738DA987BA568103EABE2CB53D23 + +21CFDC2A7CCB7F331B3D2EEFFF37E48AD9FA9C788C3F3C200E0173D99963E1CB\ +CA93623B264E920394AE48BB4C3A5BB96FFBC8F0E53F30E22956ADABC2765F57\ +FB761E147ECBF8567533DB6E50C8A1F894310A94EDF806DD8CA6A0E141C0FA7C\ +9FAE6C6AE65F18C93A8529E6E5B553BF55F25BE2E80A9882BD37F145FECBEB3D\ +447A3C4E46C21524CC55CDD62F521AB92A8BA72B897996C49BB273198B7B1C9E:\ +AFB37A28A4F216A6CC3D6AED09E82F40B93E445F892040F21D1AABAFE99AF7F0\ +01837CF0AD8DD2E2983282F35ADFB9DCEB49B2C80C85153772A8E587ABE7F18A + +4E452BA42127DCC956EF4F8F35DD68CB225FB73B5BC7E1EC5A898BBA2931563E\ +74FAFF3B67314F241EC49F4A7061E3BD0213AE826BAB380F1F14FAAB8B0EFDDD\ +5FD1BB49373853A08F30553D5A55CCBBB8153DE4704F29CA2BDEEF0419468E05\ +DD51557CCC80C0A96190BBCC4D77ECFF21C66BDF486459D427F986410F883A80\ +A5BCC32C20F0478BB9A97A126FC5F95451E40F292A4614930D054C851ACD019C\ +CF:\ +721B1BC60845499B1A50B716F97FA9FD584132C1E30A1705779DBBAE644CBB57\ +51AD1B1B379CC91BA4C3054BD060B88050BABA98BE1864B1B96C3691A096EF21 + +FA85671DF7DADF99A6FFEE97A3AB9991671F5629195049880497487867A6C446\ +B60087FAC9A0F2FCC8E3B24E97E42345B93B5F7D3691829D3F8CCD4BB36411B8\ +5FC2328EB0C51CB3151F70860AD3246CE0623A8DC8B3C49F958F8690F8E3860E\ +71EB2B1479A5CEA0B3F8BEFD87ACAF5362435EAECCB52F38617BC6C5C2C6E269\ +EAD1FBD69E941D4AD2012DA2C5B21BCFBF98E4A77AB2AF1F3FDA3233F046D38F\ +1DC8:\ +EFFFB02598398243D8784EB8ADA33D314C8D396406BB7FB6A668085B23438AB4\ +580BFB5258E5D616F9030C6A8928F4F753D6800C90EA2812482BED268A806E8E + +E90847AE6797FBC0B6B36D6E588C0A743D725788CA50B6D792352EA8294F5BA6\ +54A15366B8E1B288D84F5178240827975A763BC45C7B0430E8A559DF4488505E\ +009C63DA994F1403F407958203CEBB6E37D89C94A5EACF6039A327F6C4DBBC7A\ +2A307D976AA39E41AF6537243FC218DFA6AB4DD817B6A397DF5CA69107A91987\ +99ED248641B63B42CB4C29BFDD7975AC96EDFC274AC562D0474C60347A078CE4\ +C25E88:\ +F1CF53FFC952C446EEF49F9D89370757C74CB8F2D99223C47EABD296151161CB\ +86C6A34833E7AC6B75E8119A8274FD2B9066EBB9B787A4A37C9036E6E01BA9CE + +F6D5C2B6C93954FC627602C00C4CA9A7D3ED12B27173F0B2C9B0E4A5939398A6\ +65E67E69D0B12FB7E4CEB253E8083D1CEB724AC07F009F094E42F2D6F2129489\ +E846EAFF0700A8D4453EF453A3EDDC18F408C77A83275617FABC4EA3A2833AA7\ +3406C0E966276079D38E8E38539A70E194CC5513AAA457C699383FD1900B1E72\ +BDFB835D1FD321B37BA80549B078A49EA08152869A918CA57F5B54ED71E4FD3A\ +C5C06729:\ +F1C9A73B10BA528A61AB86F91A9A05261B447049C7ECCF37AB1E0C1219F14F0F\ +0F2C5B419A7595550F2D651A17368C3FB7538A14FF9FFC4C4D9098803D942D3B + +CF8562B1BED89892D67DDAAF3DEEB28246456E972326DBCDB5CF3FB289ACA01E\ +68DA5D59896E3A6165358B071B304D6AB3D018944BE5049D5E0E2BB819ACF67A\ +6006111089E6767132D72DD85BEDDCBB2D64496DB0CC92955AB4C6234F1EEA24\ +F2D51483F2E209E4589BF9519FAC51B4D061E801125E605F8093BB6997BC163D\ +551596FE4AB7CFAE8FB9A90F6980480CE0C229FD1675409BD788354DAF316240\ +CFE0AF93EB:\ +5A1A31490BC85FACC5101EE18093BEC7C2CB717A54AFDEE47F98660032D912F2\ +3792F1D0AB0BE8A3C7F0D000DAC238DE843CC84178CBAA910090AC827197AD85 + +2ACE31ABB0A2E3267944D2F75E1559985DB7354C6E605F18DC8470423FCA30B7\ +331D9B33C4A4326783D1CAAE1B4F07060EFF978E4746BF0C7E30CD61040BD5EC\ +2746B29863EB7F103EBDA614C4291A805B6A4C8214230564A0557BC7102E0BD3\ +ED23719252F7435D64D210EE2AAFC585BE903FA41E1968C50FD5D5367926DF7A\ +05E3A42CF07E656FF92DE73B036CF8B19898C0CB34557C0C12C2D8B84E91181A\ +F467BC75A9D1:\ +24B5A99041785BC5C5519190B4AAAF92770E35D07213A6DE55EB8811324CC63E\ +3AFCF61F973A896CFB30315873C0071E2BF3BB976A53163422A01192915B9C1E + +0D8D09AED19F1013969CE5E7EB92F83A209AE76BE31C754844EA9116CEB39A22\ +EBB6003017BBCF26555FA6624185187DB8F0CB3564B8B1C06BF685D47F3286ED\ +A20B83358F599D2044BBF0583FAB8D78F854FE0A596183230C5EF8E54426750E\ +AF2CC4E29D3BDD037E734D863C2BD9789B4C243096138F7672C232314EFFDFC6\ +513427E2DA76916B5248933BE312EB5DDE4CF70804FB258AC5FB82D58D08177A\ +C6F4756017FFF5:\ +7FF6491E79CD3F743C3D735A0AC1BC5EC3395950C65111D7BC2E5E3719AB0FE9\ +20DDA443B1FD8A8D557633B95E68354EF8F78A91A769CF0798871F8B11B77478 + +C3236B73DEB7662BF3F3DAA58F137B358BA610560EF7455785A9BEFDB035A066\ +E90704F929BD9689CEF0CE3BDA5ACF4480BCEB8D09D10B098AD8500D9B6071DF\ +C3A14AF6C77511D81E3AA8844986C3BEA6F469F9E02194C92868CD5F51646256\ +798FF0424954C1434BDFED9FACB390B07D342E992936E0F88BFD0E884A0DDB67\ +9D0547CCDEC6384285A45429D115AC7D235A717242021D1DC35641F5F0A48E84\ +45DBA58E6CB2C8EA:\ +0154D5832EC5594FF994034BE3FD3E61E7EEBC8E43C20C6CC9910F15650FBAED\ +2915087AC641DBF60A2083FF14AB084A27B5CC9A4E84C54A6B361D38C72746D5 + +B39FEB8283EADC63E8184B51DF5AE3FD41AAC8A963BB0BE1CD08AA5867D8D910\ +C669221E73243360646F6553D1CA05A84E8DC0DE05B6419EC349CA994480193D\ +01C92525F3FB3DCEFB08AFC6D26947BDBBFD85193F53B50609C6140905C53A66\ +86B58E53A319A57B962331EDE98149AF3DE3118A819DA4D76706A0424B4E1D29\ +10B0ED26AF61D150EBCB46595D4266A0BD7F651BA47D0C7F179CA28545007D92\ +E8419D48FDFBD744CE:\ +5B617AB6F6FFA82197ED058D4CFDF54398FA3CD95074A745D389C05D8DCE1B9D\ +4B9E88CE4B519017EA3A55EB89D06D2CE321F4801D079D5867EAC366BC270968 + +A983D54F503803E8C7999F4EDBBE82E9084F422143A932DDDDC47A17B0B7564A\ +7F37A99D0786E99476428D29E29D3C197A72BFAB1342C12A0FC4787FD7017D7A\ +6174049EA43B5779169EF7472BDBBD941DCB82FC73AAC45A8A94C9F2BD3477F6\ +1FD3B796F02A1B8264A214C6FEA74B7051B226C722099EC7883A462B83B6AFDD\ +4009248B8A237F605FE5A08FE7D8B45321421EBBA67BD70A0B00DDBF94BAAB7F\ +359D5D1EEA105F28DCFB:\ +1D96D1CE0C82A43D4135ED8A022A5F145AB42FDFA024C894939D6FA422EC4F62\ +1A1402113E1105A96273DD4F7884879F63EF41830A1EA0B4516937BBB2DBE44D + +E4D1C1897A0A866CE564635B74222F9696BF2C7F640DD78D7E2ACA66E1B61C64\ +2BB03EA7536AAE597811E9BF4A7B453EDE31F97B46A5F0EF51A071A2B3918DF1\ +6B152519AE3776F9F1EDAB4C2A377C3292E96408359D3613844D5EB393000283\ +D5AD3401A318B12FD1474B8612F2BB50FB6A8B9E023A54D7DDE28C43D6D8854C\ +8D9D1155935C199811DBFC87E9E0072E90EB88681CC7529714F8FB8A2C9D8856\ +7ADFB974EE205A9BF7B848:\ +DE1255FCB5A191E19B663DF4A9DC5471F39F13BE5F8A9CC1C3F6FE2844EB8CF0\ +38E7FF1825D26A8F135AAA77120925ADDB6ACC12EA1BF0E60DFA236FBE38458F + +B10C59723E3DCADD6D75DF87D0A1580E73133A9B7D00CB95EC19F5547027323B\ +E75158B11F80B6E142C6A78531886D9047B08E551E75E6261E79785366D7024B\ +D7CD9CF322D9BE7D57FB661069F2481C7BB759CD71B4B36CA2BC2DF6D3A328FA\ +EBDB995A9794A8D72155ED551A1F87C80BF6059B43FC764900B18A1C2441F748\ +7743CF84E565F61F8DD2ECE6B6CCC9444049197AAAF53E926FBEE3BFCA8BE588\ +EC77F29D211BE89DE18B15F6:\ +B17A24CA14830ED093C39E8323EC0DFD903172458D023D10FE4125D0EB4AF0E7\ +578B1EA1D5148348AB8D6CAB98B20B18BCC52A6CBA85851D2B74B20735BE6E48 + +DB11F609BABA7B0CA634926B1DD539C8CBADA24967D7ADD4D9876F77C2D80C0F\ +4DCEFBD7121548373582705CCA2495BD2A43716FE64ED26D059CFB566B3364BD\ +49EE0717BDD9810DD14D8FAD80DBBDC4CAFB37CC60FB0FE2A80FB4541B8CA9D5\ +9DCE457738A9D3D8F641AF8C3FD6DA162DC16FC01AAC527A4A0255B4D231C0BE\ +50F44F0DB0B713AF03D968FE7F0F61ED0824C55C4B5265548FEBD6AAD5C5EEDF\ +63EFE793489C39B8FD29D104CE:\ +602B683C28F25E9F20C413D2B357DCDF3E339945C5BD41FCA69FFFD2E1658F9F\ +B654B94B62BEE72087EABEF2F2F6AEDE72C7DC45DD4549CBC75465CC10D4C554 + +BEBD4F1A84FC8B15E4452A54BD02D69E304B7F32616AADD90537937106AE4E28\ +DE9D8AAB02D19BC3E2FDE1D651559E296453E4DBA94370A14DBBB2D1D4E20223\ +02EE90E208321EFCD8528AD89E46DC839EA9DF618EA8394A6BFF308E7726BAE0\ +C19BCD4BE52DA6258E2EF4E96AA21244429F49EF5CB486D7FF35CAC1BACB7E95\ +711944BCCB2AB34700D42D1EB38B5D536B947348A458EDE3DC6BD6EC547B1B0C\ +AE5B257BE36A7124E1060C170FFA:\ +E90126404BFED0DCF726CA50A6D0620305D1A84EFB0E768044D2DB920FB041E7\ +DEAA465777D312E2867E6E9E50559BB5ECE3A4ED6F844504C39E12988917FFF5 + +5ACA56A03A13784BDC3289D9364F79E2A85C12276B49B92DB0ADAA4F206D5028\ +F213F678C3510E111F9DC4C1C1F8B6ACB17A6413AA227607C515C62A733817BA\ +5E762CC6748E7E0D6872C984D723C9BB3B117EB8963185300A80BFA65CDE495D\ +70A46C44858605FCCBED086C2B45CEF963D33294DBE9706B13AF22F1B7C4CD5A\ +001CFEC251FBA18E722C6E1C4B1166918B4F6F48A98B64B3C07FC86A6B17A6D0\ +480AB79D4E6415B520F1C484D675B1:\ +D98758D0CBE6C5FEF11A4EDD8E9170FFA7F37F40914B4D836025B3FD71FA2B51\ +8164266D974A40AE2D7C3C359CA675E94B04D08D3EE56346A51B82366F1EF0F0 + +A5AAD0E4646A32C85CFCAC73F02FC5300F1982FABB2F2179E28303E447854094\ +CDFC854310E5C0F60993CEFF54D84D6B46323D930ADB07C17599B35B505F09E7\ +84BCA5985E0172257797FB53649E2E9723EFD16865C31B5C3D5113B58BB0BFC8\ +920FABDDA086D7537E66D709D050BD14D0C960873F156FAD5B3D3840CDFCDC9B\ +E6AF519DB262A27F40896AB25CC39F96984D650611C0D5A3080D5B3A1BF186AB\ +D42956588B3B58CD948970D298776060:\ +7EA57C6B9741AE7C07E11766DC6F69C83A72533126ACAFCA968832FCBC7A28DF\ +18968BB582E6933898672E322235C9D8FA310F485169C55E04672FFDA2A01099 + +06CBBE67E94A978203EAD6C057A1A5B098478B4B4CBEF5A97E93C8E42F557271\ +3575FC2A884531D7622F8F879387A859A80F10EF02708CD8F7413AB385AFC357\ +678B9578C0EBF641EF076A1A30F1F75379E9DCB2A885BDD295905EE80C0168A6\ +2A9597D10CF12DD2D8CEE46645C7E5A141F6E0E23AA482ABE5661C16E69EF1E2\ +8371E2E236C359BA4E92C25626A7B7FF13F6EA4AE906E1CFE163E91719B1F750\ +A96CBDE5FBC953D9E576CD216AFC90323A:\ +CEFB46600FC757512E917DFA063BEC761DA6140893D3B7BA01677C6D142CA296\ +0B4B016CCF9C9A175D8E83CC2F1A9D4171D6074E2405B866CDEE57683BD4334F + +F1C528CF7739874707D4D8AD5B98F7C77169DE0B57188DF233B2DC8A5B31EDA5\ +DB4291DD9F68E6BAD37B8D7F6C9C0044B3BF74BBC3D7D1798E138709B0D75E7C\ +593D3CCCDC1B20C7174B4E692ADD820ACE262D45CCFAE2077E87879634716806\ +0A162ECCA8C38C1A88350BD63BB539134F700FD4ADDD5959E255337DAA06BC86\ +358FABCBEFDFB5BC889783D843C08AADC6C4F6C36F65F156E851C9A0F917E4A3\ +67B5AD93D874812A1DE6A7B93CD53AD97232:\ +EB861B333F0763CC1F0747ECE23FF46B98962B096CBF95335B6BA9992F291611\ +5887E77A812CE6F78B00530194C71B97ABF4082F31C09F547B025B4388199E75 + +9D9F3A7ECD51B41F6572FD0D0881E30390DFB780991DAE7DB3B47619134718E6\ +F987810E542619DFAA7B505C76B7350C6432D8BF1CFEBDF1069B90A35F0D04CB\ +DF130B0DFC7875F4A4E62CDB8E525AADD7CE842520A482AC18F09442D78305FE\ +85A74E39E760A4837482ED2F437DD13B2EC1042AFCF9DECDC3E877E50FF4106A\ +D10A525230D11920324A81094DA31DEAB6476AA42F20C84843CFC1C58545EE80\ +352BDD3740DD6A16792AE2D86F11641BB717C2:\ +51CBA976ABC7E8D55F67B1A056B311B861FEE85D2FD69BED53DD274024D87DBD\ +269C41B85F6A1C19FF3D32C444CC7BD8F11478147BBCE99DCBD29E34988EA808 + +5179888724819FBAD3AFA927D3577796660E6A81C52D98E9303261D5A4A83232\ +F6F758934D50AA83FF9E20A5926DFEBAAC49529D006EB923C5AE5048ED544EC4\ +71ED7191EDF46363383824F915769B3E688094C682B02151E5EE01E510B431C8\ +865AFF8B6B6F2F59CB6D129DA79E97C6D2B8FA6C6DA3F603199D2D1BCAB54768\ +2A81CD6CF65F6551121391D78BCC23B5BD0E922EC6D8BF97C952E84DD28AEF90\ +9ABA31EDB903B28FBFC33B7703CD996215A11238:\ +10863687D6D1144DCF9D03C10CB66B33E9813EFB9118EEFB947FC68997E6CCF6\ +D93DCD4C2E33A2D187F5E6F5569D291F16B985908F4015599A6214C24AF791B9 + +576EF3520D30B7A4899B8C0D5E359E45C5189ADD100E43BE429A02FB3DE5FF4F\ +8FD0E79D9663ACCA72CD29C94582B19292A557C5B1315297D168FBB54E9E2ECD\ +13809C2B5FCE998EDC6570545E1499DBE7FB74D47CD7F35823B212B05BF3F5A7\ +9CAA34224FDD670D335FCB106F5D92C3946F44D3AFCBAE2E41AC554D8E6759F3\ +32B76BE89A0324AA12C5482D1EA3EE89DED4936F3E3C080436F539FA137E74C6\ +D3389BDF5A45074C47BC7B20B0948407A66D855E2F:\ +DE8591FD57ABD6D73CF01C94083F916C897FC0CABC1049BCD75D64C768D3B4C4\ +2F05BA4DEAAB83BB643BA451CC224B0A61110647FA35AC14F63D9C2FEA5231C9 + +0DF2152FA4F4357C8741529DD77E783925D3D76E95BAFA2B542A2C33F3D1D117\ +D159CF473F82310356FEE4C90A9E505E70F8F24859656368BA09381FA245EB6C\ +3D763F3093F0C89B972E66B53D59406D9F01AEA07F8B3B615CAC4EE4D05F542E\ +7D0DAB45D67CCCCD3A606CCBEB31EA1FA7005BA07176E60DAB7D78F6810EF086\ +F42F08E595F0EC217372B98970CC6321576D92CE38F7C397A403BADA1548D205\ +C343AC09DECA86325373C3B76D9F32028FEA8EB32515:\ +4E529B73E0AFA555B75A7EF2B43F32D71002045F0ABF519C5C1E31F7213AE10B\ +B1474BED81450E9956779216B0DC2D4067B181744D9E66AF3F34306CEFD5FDE8 + +3E15350D87D6EBB5C8AD99D42515CFE17980933C7A8F6B8BBBF0A63728CEFAAD\ +2052623C0BD5931839112A48633FB3C2004E0749C87A41B26A8B48945539D1FF\ +41A4B269462FD199BFECD45374756F55A9116E92093AC99451AEFB2AF9FD32D6\ +D7F5FBC7F7A540D5097C096EBC3B3A721541DE073A1CC02F7FB0FB1B9327FB0B\ +1218CA49C9487AB5396622A13AE546C97ABDEF6B56380DDA7012A8384091B665\ +6D0AB272D363CEA78163FF765CDD13AB1738B940D16CAE:\ +CAD6B2E517A3A890D69C8058B427CF4CE48C775B84EC7E47D12C3D2BFD746D3F\ +6DD1814F6721B5DA519A6630E581846F999F727970C67940DFFF70015DAE9053 + +C38D6B0B757CB552BE40940ECE0009EF3B0B59307C1451686F1A22702922800D\ +58BCE7A636C1727EE547C01B214779E898FC0E560F8AE7F61BEF4D75EAA696B9\ +21FD6B735D171535E9EDD267C192B99880C87997711002009095D8A7A437E258\ +104A41A505E5EF71E5613DDD2008195F0C574E6BA3FE40099CFA116E5F1A2FA8\ +A6DA04BADCB4E2D5D0DE31FDC4800891C45781A0AAC7C907B56D631FCA5CE8B2\ +CDE620D11D1777ED9FA603541DE794DDC5758FCD5FAD78C0:\ +24C90C5D7F0C9471FA119437C8CA847E81D556F66FB6316DD0FB53DD57DFB3BA\ +7D14AC4D1C9C55F04FB6FE2EA9E67178890A3501567059015B7D993256CA1C54 + +8D2DE3F0B37A6385C90739805B170057F091CD0C7A0BC951540F26A5A75B3E69\ +4631BB64C7635EED316F51318E9D8DE13C70A2ABA04A14836855F35E480528B7\ +76D0A1E8A23B547C8B8D6A0D09B241D3BE9377160CCA4E6793D00A515DC2992C\ +B7FC741DACA171431DA99CCE6F7789F129E2AC5CF65B40D703035CD2185BB936\ +C82002DAF8CBC27A7A9E554B06196630446A6F0A14BA155ED26D95BD627B7205\ +C072D02B60DB0FD7E49EA058C2E0BA202DAFF0DE91E845CF79:\ +4BA61EFF8CEC62389A932E24775211189098BDCDFDC6615AE79948914D6361C6\ +BBC45B7DEAFB4A58B78AF4ABFBEB8991EDCF30A2A586BE8C6CECF9875C734D7A + +C464BBDAD275C50DCD983B65AD1019B9FF85A1E71C807F3204BB2C921DC31FBC\ +D8C5FC45868AE9EF85B6C9B83BBA2A5A822201ED68586EC5EC27FB2857A5D1A2\ +D09D09115F22DCC39FE61F5E1BA0FF6E8B4ACB4C6DA748BE7F3F0839739394FF\ +7FA8E39F7F7E84A33C3866875C01BCB1263C9405D91908E9E0B50E7459FABB63\ +D8C6BBB73D8E3483C099B55BC30FF092FF68B6ADEDFD477D63570C9F5515847F\ +36E24BA0B705557130CEC57EBAD1D0B31A378E91894EE26E3A04:\ +1F6CD40F56856615AAFD4103618908530C8EEF746389ADCE64E2CADFFBACB9DA\ +B4E5F973CBB86E607AF00F32948E4CF8BAFD2782653710B38FBF890922773AE5 + +8B8D68BB8A75732FE272815A68A1C9C5AA31B41DEDC8493E76525D1D013D33CE\ +BD9E21A5BB95DB2616976A8C07FCF411F5F6BC6F7E0B57ACA78CC2790A6F9B89\ +8858AC9C79B165FF24E66677531E39F572BE5D81EB3264524181115F32780257\ +BFB9AEEC6AF12AF28E587CAC068A1A2953B59AD680F4C245B2E3EC36F59940D3\ +7E1D3DB38E13EDB29B5C0F404F6FF87F80FC8BE7A225FF22FBB9C8B6B1D7330C\ +57840D24BC75B06B80D30DAD6806544D510AF6C4785E823AC3E0B8:\ +2E6D38768361D7BA583A5314947E43FA294E29F87BD7CC2D6F49890912885F90\ +7D8FA6BEF24B4824A4FF777C5FCF04D655FB0F9C2A6C7ADABEC9B92A6698D33E + +6B018710446F368E7421F1BC0CCF562D9C1843846BC8D98D1C9BF7D9D6FCB48B\ +FC3BF83B36D44C4FA93430AF75CD190BDE36A7F92F867F58A803900DF8018150\ +384D85D82132F123006AC2AEBA58E02A037FE6AFBD65ECA7C44977DD3DC74F48\ +B6E7A1BFD5CC4DCF24E4D52E92BD4455848E4928B0EAC8B7476FE3CC03E862AA\ +4DFF4470DBFED6DE48E410F25096487ECFC32A27277F3F5023B2725ADE461B13\ +55889554A8836C9CF53BD767F5737D55184EEA1AB3F53EDD0976C485:\ +EB395350C2557F16601D19DC75031348103F059A0FB890CC2A002932E0619CE8\ +E52F0F39688DF0DB724CB095B69A5643154C9336FBBA50F35C6A4C05477737EC + +C9534A24714BD4BE37C88A3DA1082EDA7CABD154C309D7BD670DCCD95AA53559\ +4463058A29F79031D6ECAA9F675D1211E9359BE82669A79C855EA8D89DD38C2C\ +761DDD0EC0CE9E97597432E9A1BEAE062CDD71EDFDFD464119BE9E69D18A7A7F\ +D7CE0E2106F0C8B0ABF4715E2CA48EF9F454DC203C96656653B727083513F8EF\ +B86E49C513BB758B3B052FE21F1C05BB33C37129D6CC81F1AEF6ADC45B0E8827\ +A830FE545CF57D0955802C117D23CCB55EA28F95C0D8C2F9C5A242B33F:\ +01449772284E566C1E31A6924A2D9157BDCDD694B5ED1039370BBB11F58851FE\ +5677B25276EC84FDD8472426735C532BCA3D59ACB6FDCE13C0DEA9376DDA8AAE + +07906C87297B867ABF4576E9F3CC7F82F22B154AFCBF293B9319F1B0584DA6A4\ +0C27B32E0B1B7F412C4F1B82480E70A9235B12EC27090A5A33175A2BB28D8ADC\ +475CEFE33F7803F8CE27967217381F02E67A3B4F84A71F1C5228E0C2AD971373\ +F6F672624FCEA8D1A9F85170FAD30FA0BBD25035C3B41A6175D467998BD1215F\ +6F3866F53847F9CF68EF3E2FBB54BC994DE2302B829C5EEA68EC441FCBAFD7D1\ +6AE4FE9FFF98BF00E5BC2AD54DD91FF9FDA4DD77B6C754A91955D1FBAAD0:\ +5E4DE3451E6BF67CEC13F960D86FA9035B1AA4A824F0AFF446271D39784A0E73\ +5FDD00AE53D6347DDFEC4EC6A552AD78AF145BBA1CD4C34C300E3AAEEF88838E + +588E94B9054ABC2189DF69B8BA34341B77CDD528E7860E5DEFCAA79B0C9A452A\ +D4B82AA306BE84536EB7CEDCBE058D7B84A6AEF826B028B8A0271B69AC3605A9\ +635EA9F5EA0AA700F3EB7835BC54611B922964300C953EFE7491E3677C2CEBE0\ +822E956CD16433B02C68C4A23252C3F9E151A416B4963257B783E038F6B4D5C9\ +F110F871652C7A649A7BCEDCBCCC6F2D0725BB903CC196BA76C76AA9F10A190B\ +1D1168993BAA9FFC96A1655216773458BEC72B0E39C9F2C121378FEAB4E76A:\ +814E7B36373B0276718212ABA4E0D9760E433B680FC59869533E4F1D34010047\ +977C91FA33C0C6DFC2F6A4DADCE34BC897A3F7E2CA9935B99D8E5425AB46060D + +08959A7E4BAAE874928813364071194E2939772F20DB7C3157078987C557C2A6\ +D5ABE68D520EEF3DC491692E1E21BCD880ADEBF63BB4213B50897FA005256ED4\ +1B5690F78F52855C8D9168A4B666FCE2DA2B456D7A7E7C17AB5F2FB1EE90B79E\ +698712E963715983FD07641AE4B4E9DC73203FAC1AE11FA1F8C7941FCC82EAB2\ +47ADDB56E2638447E9D609E610B60CE086656AAEBF1DA3C8A231D7D94E2FD0AF\ +E46B391FF14A72EAEB3F44AD4DF85866DEF43D4781A0B3578BC996C87970B132:\ +9B28504942E11B4FE971337FBB905DD772EF9D4982AC4D5EC7C3EFCEBBD1F32D\ +6BC7EDCE173A75DE81C5651A3D1DD22A5D63A2763986356331F18BD02D77B036 + +CB2A234F45E2ECD5863895A451D389A369AAB99CFEF0D5C9FFCA1E6E63F763B5\ +C14FB9B478313C8E8C0EFEB3AC9500CF5FD93791B789E67EAC12FD038E2547CC\ +8E0FC9DB591F33A1E4907C64A922DDA23EC9827310B306098554A4A78F050262\ +DB5B545B159E1FF1DCA6EB734B872343B842C57EAFCFDA8405EEDBB48EF32E99\ +696D135979235C3A05364E371C2D76F1902F1D83146DF9495C0A6C57D7BF9EE7\ +7E80F9787AEE27BE1FE126CDC9EF893A4A7DCBBC367E40FE4E1EE90B42EA25AF\ +01:\ +563AAB317672C0DAFC3578FD23DD1416A577D76099B850801C82B03A7FD9037D\ +DC84E7960817B893C2AA5444C46CC5ACED01821E0A299A8BFC13860B6DE3A0C2 + +D16BEADF02AB1D4DC6F88B8C4554C51E866DF830B89C06E786A5F8757E890931\ +0AF51C840EFE8D20B35331F4355D80F73295974653DDD620CDDE4730FB6C8D0D\ +2DCB2B45D92D4FBDB567C0A3E86BD1A8A795AF26FBF29FC6C65941CDDB090FF7\ +CD230AC5268AB4606FCCBA9EDED0A2B5D014EE0C34F0B2881AC036E24E151BE8\ +9EEB6CD9A7A790AFCCFF234D7CB11B99EBF58CD0C589F20BDAC4F9F0E28F75E3\ +E04E5B3DEBCE607A496D848D67FA7B49132C71B878FD5557E082A18ECA1FBDA9\ +4D4B:\ +7365A562E0A02312B2B26D583CA242C479A96F50827B4E87B4E7D4F4B4174C39\ +A76E843FB1D3D2F3731B06161A02BA5E64860D916E607BB5954765B34F57072C + +8F65F6BC59A85705016E2BAE7FE57980DE3127E5AB275F573D334F73F8603106\ +EC3553016608EF2DD6E69B24BE0B7113BF6A760BA6E9CE1C48F9E186012CF96A\ +1D4849D75DF5BB8315387FD78E9E153E76F8BA7EC6C8849810F59FB4BB9B0043\ +18210B37F1299526866F44059E017E22E96CBE418699D014C6EA01C9F0038B10\ +299884DBEC3199BB05ADC94E955A1533219C1115FED0E5F21228B071F40DD57C\ +4240D98D37B73E412FE0FA4703120D7C0C67972ED233E5DEB300A22605472FA3\ +A3BA86:\ +8B9F0CD8D4D56DCB17BB67DB05580A6B67296D4CA8297CA8A705ED9C9948EA9B\ +1DE211D205DF7836DA88C2CEA2ADDA29124E9DD9D5A95AA7E300BFC52E8931DB + +84891E52E0D451813210C3FD635B39A03A6B7A7317B221A7ABC270DFA946C426\ +69AACBBBDF801E1584F330E28C729847EA14152BD637B3D0F2B38B4BD5BF9C79\ +1C58806281103A3EABBAEDE5E711E539E6A8B2CF297CF351C078B4FA8F7F35CF\ +61BEBF8814BF248A01D41E86C5715EA40C63F7375379A7EB1D78F27622FB468A\ +B784AAABA4E534A6DFD1DF6FA15511341E725ED2E87F98737CCB7B6A6DFAE416\ +477472B046BF1811187D151BFA9F7B2BF9ACDB23A3BE507CDF14CFDF517D2CB5\ +FB9E4AB6:\ +34C0FFBFE39B0ABD5B261D66499A8508F360B0D61296DB24E2496C2EDEBE80C2\ +642C12976FA54EF41A766F6722393D7B154AA0BC5C4E20A2CE0527F9A16C3AAC + +FDD7A9433A3B4AFABD7A3A5E3457E56DEBF78E84B7A0B0CA0E8C6D53BD0C2DAE\ +31B2700C6128334F43981BE3B213B1D7A118D59C7E6B6493A86F866A1635C128\ +59CFB9AD17460A77B4522A5C1883C3D6ACC86E6162667EC414E9A104AA892053\ +A2B1D72165A855BACD8FAF8034A5DD9B716F47A0818C09BB6BAF22AA503C06B4\ +CA261F557761989D2AFBD88B6A678AD128AF68672107D0F1FC73C5CA74045929\ +7B3292B281E93BCEB761BDE7221C3A55708E5EC84472CDDCAA84ECF23723CC09\ +91355C6280:\ +2EB1C4BD6D8E41981756A7F83A41D5DF0FC770707AFE22DADEE6BF92DF54096F\ +C4AEB6E0114AC3CBB33BD8D6A47260BAF4127CDE97371979B21E8E32EA205265 + +70A40BFBEF92277A1AAD72F6B79D0177197C4EBD432668CFEC05D099ACCB6510\ +62B5DFF156C0B27336687A94B26679CFDD9DAF7AD204338DD9C4D14114033A5C\ +225BD11F217B5F4732DA167EE3F939262D4043FC9CBA92303B7B5E96AEA12ADD\ +A64859DF4B86E9EE0B58E39091E6B188B408AC94E1294A8911245EE361E60E60\ +1EFF58D1D37639F3753BEC80EBB4EFDE25817436076623FC65415FE51D1B0280\ +366D12C554D86743F3C3B6572E400361A60726131441BA493A83FBE9AFDA90F7\ +AF1AE717238D:\ +18485311BE9C848C38BFA25EC4C557196F1E39A4AC812B77AD2975182A9C2768\ +706905562B0722A2A1B92A56EB47E2500EC1621F59B6B0059EE6FF8C2DB29326 + +74356E449F4BF8644F77B14F4D67CB6BD9C1F5AE357621D5B8147E562B65C665\ +85CAF2E491B48529A01A34D226D436959153815380D5689E30B35357CDAC6E08\ +D3F2B0E88E200600D62BD9F5EAF488DF86A4470EA227006182E44809009868C4\ +C280C43D7D64A5268FA719074960087B3A6ABC837882F882C837834535929389\ +A12B2C78187E2EA07EF8B8EEF27DC85002C3AE35F1A50BEE6A1C48BA7E175F33\ +16670B27983472AA6A61EED0A683A39EE323080620EA44A9F74411AE5CE99030\ +528F9AB49C79F2:\ +753B20F511FD288F732ADE82C0F97D7A05DC4E6B931F7D1D0F266911A3C7DDBA\ +5DB2BB233A12D9508DC071E760844F376AC74CDACC5C8321DB2E6DDA9EF2F9D1 + +8C3798E51BC68482D7337D3ABB75DC9FFE860714A9AD73551E120059860DDE24\ +AB87327222B64CF774415A70F724CDF270DE3FE47DDA07B61C9EF2A3551F45A5\ +584860248FABDE676E1CD75F6355AA3EAEABE3B51DC813D9FB2EAA4F0F1D9F83\ +4D7CAD9C7C695AE84B329385BC0BEF895B9F1EDF44A03D4B410CC23A79A6B62E\ +4F346A5E8DD851C2857995DDBF5B2D717AEB847310E1F6A46AC3D26A7F9B4498\ +5AF656D2B7C9406E8A9E8F47DCB4EF6B83CAACF9AEFB6118BFCFF7E44BEF6937\ +EBDDC89186839B77:\ +E4ECE8FA8A82C0C44328A5B11C0C0EAB3B165A919555B8ECD121A828B0892E16\ +86EF62EAAD10C87B41BCCD85E60F37AEAE96503FBCE970D895E1E1E551CE1A85 + +FA56BF730C4F8395875189C10C4FB251605757A8FECC31F9737E3C2503B02608\ +E6731E85D7A38393C67DE516B85304824BFB135E33BF22B3A23B913BF6ACD2B7\ +AB85198B8187B2BCD454D5E3318CACB32FD6261C31AE7F6C54EF6A7A2A4C9F3E\ +CB81CE3555D4F0AD466DD4C108A90399D70041997C3B25345A9653F3C9A6711A\ +B1B91D6A9D2216442DA2C973CBD685EE7643BFD77327A2F7AE9CB283620A0871\ +6DFB462E5C1D65432CA9D56A90E811443CD1ECB8F0DE179C9CB48BA4F6FEC360\ +C66F252F6E64EDC96B:\ +0C2A1D85CB308CEA8D84108224FC6DA66A2654496A14CAB4457B672EF9BD2D25\ +F0D14098334846F0187D01D74CF8B18C22B3CF9E00ED31F1BE30E960E3C26AF1 + +B6134F9C3E91DD8000740D009DD806240811D51AB1546A974BCB18D344642BAA\ +5CD5903AF84D58EC5BA17301D5EC0F10CCD0509CBB3FD3FFF9172D193AF0F782\ +252FD1338C7244D40E0E42362275B22D01C4C3389F19DD69BDF958EBE28E31A4\ +FFE2B5F18A87831CFB7095F58A87C9FA21DB72BA269379B2DC2384B3DA953C79\ +25761FED324620ACEA435E52B424A7723F6A2357374157A34CD8252351C25A1B\ +232826CEFE1BD3E70FFC15A31E7C0598219D7F00436294D11891B82497BC78AA\ +5363892A2495DF8C1EEF:\ +46C390535747C9C16A4797C28DDEE9C2CECC3B8F1A89EE67C91A0D06220E6633\ +9E7B4A7D6C6B2B27D0A011D51BF7EA0DD61E6124D329269BCD4B92273C2A311D + +C941CDB9C28AB0A791F2E5C8E8BB52850626AA89205BEC3A7E22682313D198B1\ +FA33FC7295381354858758AE6C8EC6FAC3245C6E454D16FA2F51C4166FAB51DF\ +272858F2D603770C40987F64442D487AF49CD5C3991CE858EA2A60DAB6A65A34\ +414965933973AC2457089E359160B7CDEDC42F29E10A91921785F6B7224EE0B3\ +49393CDCFF6151B50B377D609559923D0984CDA6000829B916AB6896693EF6A2\ +199B3C22F7DC5500A15B8258420E314C222BC000BC4E5413E6DD82C993F8330F\ +5C6D1BE4BC79F08A1A0A46:\ +6C7060DBE2F17BAE9F4503FA61FCB2B3C6F9F8E1710FD2092CAB5865E05C6E3A\ +9A5D2E5A94E4C9DAFB9F3E47E52A6644990D8F397C93DAD4546A7C1C35BE8CA7 + +4499EFFFAC4BCEA52747EFD1E4F20B73E48758BE915C88A1FFE5299B0B005837\ +A46B2F20A9CB3C6E64A9E3C564A27C0F1C6AD1960373036EC5BFE1A8FC6A435C\ +2185ED0F114C50E8B3E4C7ED96B06A036819C9463E864A58D6286F785E32A804\ +443A56AF0B4DF6ABC57ED5C2B185DDEE8489EA080DEEEE66AA33C2E6DAB36251\ +C402682B6824821F998C32163164298E1FAFD31BABBCFFB594C91888C6219079\ +D907FDB438ED89529D6D96212FD55ABE20399DBEFD342248507436931CDEAD49\ +6EB6E4A80358ACC78647D043:\ +A614F68BE815612E5E571B06DC69C3C86A8A4EFF9BBA9A981413F60C7B612B90\ +6A7805BE3E292F1154CB0E1B003B86F40B23B99C579DA381D06C734E60A49806 + +EECBB8FDFA4DA62170FD06727F697D81F83F601FF61E478105D3CB7502F2C89B\ +F3E8F56EDD469D049807A38882A7EEFBC85FC9A950952E9FA84B8AFEBD3CE782\ +D4DA598002827B1EB98882EA1F0A8F7AA9CE013A6E9BC462FB66C8D4A18DA214\ +01E1B93356EB12F3725B6DB1684F2300A98B9A119E5D27FF704AFFB618E12708\ +E77E6E5F34139A5A41131FD1D6336C272A8FC37080F041C71341BEE6AB550CB4\ +A20A6DDB6A8E0299F2B14BC730C54B8B1C1C487B494BDCCFD3A53535AB2F2315\ +90BF2C4062FD2AD58F906A2D0D:\ +402CC283CF76060F64F0DE59D14910D710221F63537D5E30A1388496CC2260DE\ +1E3BCACE354FC1AB344458DD9BEDF3FC36336D67B10EF21FC6D6F48ACD265C8D + +E64F3E4ACE5C8418D65FEC2BC5D2A303DD458034736E3B0DF719098BE7A206DE\ +AF52D6BA82316CAF330EF852375188CDE2B39CC94AA449578A7E2A8E3F5A9D68\ +E816B8D16889FBC0EBF0939D04F63033AE9AE2BDAB73B88C26D6BD25EE460EE1\ +EF58FB0AFA92CC539F8C76D3D097E7A6A63EBB9B5887EDF3CF076028C5BBD5B9\ +DB3211371AD3FE121D4E9BF44229F4E1ECF5A0F9F0EBA4D5CEB72878AB22C3F0\ +EB5A625323AC66F7061F4A81FAC834471E0C59553F108475FE290D43E6A055AE\ +3EE46FB67422F814A68C4BE3E8C9:\ +AEF42FDB10807FDAEA631638A64C06A9125CDB7F94BB91AB345E1EA30E606FC5\ +FBC6322075A50FE2D13D19FD34AB072C41B96CED205CC5143A1A5C98DEA311D0 + +D2CB2D733033F9E91395312808383CC4F0CA974E87EC68400D52E96B3FA6984A\ +C58D9AD0938DDE5A973008D818C49607D9DE2284E7618F1B8AED8372FBD52ED5\ +4557AF4220FAC09DFA8443011699B97D743F8F2B1AEF3537EBB45DCC9E13DFB4\ +38428EE190A4EFDB3CAEB7F3933117BF63ABDC7E57BEB4171C7E1AD260AB0587\ +806C4D137B6316B50ABC9CCE0DFF3ACADA47BBB86BE777E617BBE578FF451984\ +4DB360E0A96C6701290E76BB95D26F0F804C8A4F2717EAC4E7DE9F2CFF3BBC55\ +A17E776C0D02856032A6CD10AD2838:\ +391C3A33EC4B5D75C910DF0F00F6AD5D4E8844CDB364B2D7B0155BDD4F9C0E1B\ +6C7825938F642840D06CD0E6F67F87DCCC34F6FD83587FD9266D603CA625548F + +F2998955613DD414CC111DF5CE30A995BB792E260B0E37A5B1D942FE90171A4A\ +C2F66D4928D7AD377F4D0554CBF4C523D21F6E5F379D6F4B028CDCB9B1758D3B\ +39663242FF3CB6EDE6A36A6F05DB3BC41E0D861B384B6DEC58BB096D0A422FD5\ +42DF175E1BE1571FB52AE66F2D86A2F6824A8CFAACBAC4A7492AD0433EEB1545\ +4AF8F312B3B2A577750E3EFBD370E8A8CAC1582581971FBA3BA4BD0D76E718DA\ +CF8433D33A59D287F8CC92234E7A271041B526E389EFB0E40B6A18B3AAF658E8\ +2ED1C78631FD23B4C3EB27C3FAEC8685:\ +E51079072C571D0E44C975F232F052F78B497A1C85995E194691A85AB026E4F8\ +0A4993D3A2B4D69F607558CEFF54D766915E5A4E0C7A42C8D307FA03C6DC4C74 + +447797E2899B72A356BA55BF4DF3ACCA6CDB1041EB477BD1834A9F9ACBC340A2\ +94D729F2F97DF3A610BE0FF15EDB9C6D5DB41644B9874360140FC64F52AA03F0\ +286C8A640670067A84E017926A70438DB1BB361DEFEE7317021425F8821DEF26\ +D1EFD77FC853B818545D055ADC9284796E583C76E6FE74C9AC2587AA46AA8F88\ +04F2FEB5836CC4B3ABABAB8429A5783E17D5999F32242EB59EF30CD7ADABC16D\ +72DBDB097623047C98989F88D14EAF02A7212BE16EC2D07981AAA99949DDF89E\ +CD90333A77BC4E1988A82ABF7C7CAF3291:\ +019BE27AC6E4B1FB3F1602025A8DE3EFA7AD6E1D0C6975E8D2D519A997328154\ +FE0738A00366205FDF8467B36D8970A92EF450C20F5BEC013BA4CF8091F571CB + +9F2C18ADE9B380C784E170FB763E9AA205F64303067EB1BCEA93DF5DAC4BF5A2\ +E00B78195F808DF24FC76E26CB7BE31DC35F0844CDED1567BBA29858CFFC97FB\ +29010331B01D6A3FB3159CC1B973D255DA9843E34A0A4061CABDB9ED37F241BF\ +ABB3C20D32743F4026B59A4CCC385A2301F83C0B0A190B0F2D01ACB8F0D41111\ +E10F2F4E149379275599A52DC089B35FDD5234B0CFB7B6D8AEBD563CA1FA653C\ +5C021DFD6F5920E6F18BFAFDBECBF0AB00281333ED50B9A999549C1C8F8C63D7\ +626C48322E9791D5FF72294049BDE91E73F8:\ +B996713F0A3AB5F0198C127B5C3079DACE7D4D98A9433D9B790833B62395A379\ +7B7924EB8B9F586903079A8413597E37448F3222B751DEBE8A5B83385864F7B8 + +AE159F3FA33619002AE6BCCE8CBBDD7D28E5ED9D61534595C4C9F43C402A9BB3\ +1F3B301CBFD4A43CE4C24CD5C9849CC6259ECA90E2A79E01FFBAC07BA0E147FA\ +42676A1D668570E0396387B5BCD599E8E66AAED1B8A191C5A47547F61373021F\ +A6DEADCB55363D233C24440F2C73DBB519F7C9FA5A8962EFD5F6252C0407F190\ +DFEFAD707F3C7007D69FF36B8489A5B6B7C557E79DD4F50C06511F599F56C896\ +B35C917B63BA35C6FF8092BAF7D1658E77FC95D8A6A43EEB4C01F33F03877F92\ +774BE89C1114DD531C011E53A34DC248A2F0E6:\ +FB71A3351EA2FD4C44E271EA793596B245C6F0634E79ED1EC72C6A4CC9DBC892\ +A9498A7ACA0915AB20B0DAED223FAD794A6F3822C847CF52B3F217D0BC605B76 + +3B8E97C5FFC2D6A40FA7DE7FCEFC90F3B12C940E7AB415321E29EE692DFAC799\ +B009C99DCDDB708FCE5A178C5C35EE2B8617143EDC4C40B4D313661F49ABDD93\ +CEA79D117518805496FE6ACF292C4C2A1F76B403A97D7C399DAF85B46AD84E16\ +246C67D6836757BDE336C290D5D401E6C1386AB32797AF6BB251E9B2D8FE754C\ +47482B72E0B394EAB76916126FD68EA7D65EB93D59F5B4C5AC40F7C3B37E7F36\ +94F29424C24AF8C8F0EF59CD9DBF1D28E0E10F799A6F78CAD1D45B9DB3D7DEE4\ +A7059ABE99182714983B9C9D44D7F5643596D4F3:\ +DBD3650B1739E8DA775381B5521C5CFDD689FE81309B3A69A4B3BCDC62DD6C45\ +68B84670E5E3B1B4E0E834600C36167E3447C5C1009E680C7932DB2BD91057A9 + +3434EC31B10FAFDBFEEC0DD6BD94E80F7BA9DCA19EF075F7EB017512AF66D6A4\ +BCF7D16BA0819A1892A6372F9B35BCC7CA8155EE19E8428BC22D214856ED5FA9\ +374C3C09BDE169602CC219679F65A1566FC7316F4CC3B631A18FB4449FA6AFA1\ +6A3DB2BC4212EFF539C67CF184680826535589C7111D73BFFCE431B4C40492E7\ +63D9279560AAA38EB2DC14A212D723F994A1FE656FF4DD14551CE4E7C621B2AA\ +5604A10001B2878A897A28A08095C325E10A26D2FB1A75BFD64C250309BB55A4\ +4F23BBAC0D5516A1C687D3B41EF2FBBF9CC56D4739:\ +55B84F2AC0B917467F20E9EC5F6CE98B3987C59A1ACAEFE3AD73D1C26D724CA0\ +C4D8052CE82E3C704C7834499BEC67620D4B073BF3DA41AAD2DE69AFA4943E3B + +7C7953D81C8D208FD1C97681D48F49DD003456DE60475B84070EF4847C333B74\ +575B1FC8D2A186964485A3B8634FEAA3595AAA1A2F4595A7D6B6153563DEE31B\ +BAC443C8A33EED6D5D956A980A68366C2527B550EE950250DFB691EACBD5D56A\ +E14B970668BE174C89DF2FEA43AE52F13142639C884FD62A3683C0C3792F0F24\ +AB1318BCB27E21F4737FAB62C77EA38BC8FD1CF41F7DAB64C13FEBE7152BF5BB\ +7AB5A78F5346D43CC741CB6F72B7B8980F268B68BF62ABDFB1577A52438FE14B\ +591498CC95F071228460C7C5D5CEB4A7BDE588E7F21C:\ +AD4231D8A6C04C1517D1091D399110019055D5C5EE1D3D75456DA17C5572C10B\ +B8B808493C3A69EBD668AFFD15A9E92A692A3C7A394F929B1E7798E692979665 + +7A6A4F4FDC59A1D223381AE5AF498D74B7252ECF59E389E49130C7EAEE626E7B\ +D9897EFFD92017F4CCDE66B0440462CDEDFD352D8153E6A4C8D7A0812F701CC7\ +37B5178C2556F07111200EB627DBC299CAA792DFA58F35935299FA3A3519E9B0\ +3166DFFA159103FFA35E8577F7C0A86C6B46FE13DB8E2CDD9DCFBA85BDDDCCE0\ +A7A8E155F81F712D8E9FE646153D3D22C811BD39F830433B2213DD46301941B5\ +9293FD0A33E2B63ADBD95239BC01315C46FDB678875B3C81E053A40F581CFBEC\ +24A1404B1671A1B88A6D06120229518FB13A74CA0AC5AE:\ +70CDAED98ECA25B7099C73201427DE23F51D7115160A105DED7A2FB6B20F2DEB\ +31B6A2734CFFC2AA6189DAEA538291B34D0AAC7CA9C57CA7063A31EF202F38EC + +D9FAA14CEBE9B7DE551B6C0765409A33938562013B5E8E0E1E0A6418DF7399D0\ +A6A771FB81C3CA9BD3BB8E2951B0BC792525A294EBD1083688806FE5E7F1E17F\ +D4E3A41D00C89E8FCF4A363CAEDB1ACB558E3D562F1302B3D83BB886ED27B760\ +33798131DAB05B4217381EAAA7BA15EC820BB5C13B516DD640EAEC5A27D05FDF\ +CA0F35B3A5312146806B4C0275BCD0AAA3B2017F346975DB566F9B4D137F4EE1\ +0644C2A2DA66DEECA5342E236495C3C6280528BFD32E90AF4CD9BB908F34012B\ +52B4BC56D48CC8A6B59BAB014988EABD12E1A0A1C2E170E7:\ +45186098139174A1D4D657A79B71E6E4FB3AE790A52FF0A1690D787FCB6FBA70\ +25CF74E3CDBFAA5B2B6D1880699315FAC59FB18714C65D5EA66E6B1D47AE17C4 + +2D8427433D0C61F2D96CFE80CF1E932265A191365C3B61AAA3D6DCC039F6BA2A\ +D52A6A8CC30FC10F705E6B7705105977FA496C1C708A277A124304F1FC40911E\ +7441D1B5E77B951AAD7B01FD5DB1B377D165B05BBF898042E39660CAF8B279FE\ +5229D1A8DB86C0999ED65E53D01CCBC4B43173CCF992B3A14586F6BA42F5FE30\ +AFA8AE40C5DF29966F9346DA5F8B35F16A1DE3AB6DE0F477D8D8660918060E88\ +B9B9E9CA6A4207033B87A812DBF5544D39E4882010F82B6CE005F8E8FF6FE3C3\ +806BC2B73C2B83AFB704345629304F9F86358712E9FAE3CA3E:\ +7E804307383AFF5BCC80306043721A173E61461E401C1331ED95B8ADB1CFF5CD\ +0943CB3BA8C9A7A02987DD9B6EA2912368284CF14A55566BF264CC244A353227 + +5E19D97887FCAAC0387E22C6F803C34A3DACD2604172433F7A8A7A526CA4A2A1\ +271ECFC5D5D7BE5AC0D85D921095350DFC65997D443C21C8094E0A3FEFD2961B\ +CB94AED03291AE310CCDA75D8ACE4BC7D89E7D3E5D1650BDA5D668B8B50BFC8E\ +608E184F4D3A9A2BADC4FF5F07E0C0BC8A9F2E0B2A26FD6D8C550008FAAAB75F\ +D71AF2A424BEC9A7CD9D83FAD4C8E9319115656A8717D3B523A68FF8004258B9\ +990ED362308461804BA3E3A7E92D8F2FFAE5C2FBA55BA5A3C27C0A2F71BD711D\ +2FE1799C2ADB31B200035481E9EE5C4ADF2AB9C0FA50B23975CF:\ +8B907F2B968634263C0CC229E917FDF0AD93D637299C10D8F76EFFEE6C6A6B83\ +85803FABEDEB1694EACBC11D94FD00CD310C287C2C537BDE39B88A4A15735DF3 + +C8E976AB4638909387CE3B8D4E510C3230E5690E02C45093B1D297910ABC481E\ +56EEA0F296F98379DFC9080AF69E73B2399D1C143BEE80AE1328162CE1BA7F6A\ +8374679B20AACD380EB4E61382C99998704D62701AFA914F9A2705CDB065885F\ +50D086C3EB5753700C387118BB142F3E6DA1E988DFB31AC75D7368931E45D139\ +1A274B22F83CEB072F9BCABC0B216685BFD789F5023971024B1878A205442522\ +F9EA7D8797A4102A3DF41703768251FD5E017C85D1200A464118AA35654E7CA3\ +9F3C375B8EF8CBE7534DBC64BC20BEFB417CF60EC92F63D9EE7397:\ +4739DB195476A74B06835BA91DD8DFDADE704A06557307E33019738083F36714\ +3C96ECF28523C1BE8CA272ADF7E0EEBB64EEF31FE4C5EF03CE7D46ED6FC86A71 + +7145FA124B7429A1FC2231237A949BA7201BCC1822D3272DE005B682398196C2\ +5F7E5CC2F289FBF44415F699CB7FE6757791B1443410234AE061EDF623359E2B\ +4E32C19BF88450432DD01CAA5EB16A1DC378F391CA5E3C4E5F356728BDDD4975\ +DB7C890DA8BBC84CC73FF244394D0D48954978765E4A00B593F70F2CA082673A\ +261ED88DBCEF1127728D8CD89BC2C597E9102CED6010F65FA75A14EBE467FA57\ +CE3BD4948B6867D74A9DF5C0EC6F530CBF2EE61CE6F06BC8F2864DFF5583776B\ +31DF8C7FFCB61428A56BF7BD37188B4A5123BBF338393AF46EDA85E6:\ +68B8AA5731F7D00D547D7E3690761046B54E91257984A46E2CF9BA2835ADB621\ +CE3DDCF81A02A95308300F1E992E3BEDF832FC0433F0A64D5CE277E679933E47 + +7FDFADCC9D29BAD23AE038C6C65CDA1AEF757221B8872ED3D75FF8DF7DA0627D\ +266E224E812C39F7983E4558BFD0A1F2BEF3FEB56BA09120EF762917B9C09386\ +7948547AEE98600D10D87B20106878A8D22C64378BF634F7F75900C03986B077\ +B0BF8B740A82447B61B99FEE5376C5EB6680EC9E3088F0BDD0C56883413D60C1\ +357D3C811950E5890E7600103C916341B80C743C6A852B7B4FB60C3BA21F3BC1\ +5B8382437A68454779CF3CD7F9F90CCC8EF28D0B706535B1E4108EB5627BB45D\ +719CB046839AEE311CA1ABDC8319E050D67972CB35A6B1601B25DBF487:\ +2CD87427875CC3480CD19F567B049B1181D7F46B85F3CDE505005452A0401A51\ +7E0E3D2A2157D789A6D63C8484386EFA9F9717498D35B20CA2A0FD2FDDDF7E15 + +988638219FD3095421F826F56E4F09E356296B628C3CE6930C9F2E758FD1A80C\ +8273F2F61E4DAAE65C4F110D3E7CA0965AC7D24E34C0DC4BA2D6FF0BF5BBE93B\ +3585F354D7543CB542A1AA54674D375077F2D360A8F4D42F3DB131C3B7AB7306\ +267BA107659864A90C8C909460A73621D1F5D9D3FD95BEB19B23DB1CB6C0D0FB\ +A91D36891529B8BD8263CAA1BAB56A4AFFAED44962DF096D8D5B1EB845EF3118\ +8B3E10F1AF811A13F156BEB7A288AAE593EBD1471B624AA1A7C6ADF01E2200B3\ +D72D88A3AED3100C88231E41EFC376906F0B580DC895F080FDA5741DB1CB:\ +5E0A947E07586E1A7EB441B4F44211F3731595E273FBE30FD5478E762C08411D\ +B9DDAA9F9B9D860F5768DF78FBEAF9EFEB9ECAEE9A9874FD38E9EBDE9DDF11E7 + +5AAB62756D307A669D146ABA988D9074C5A159B3DE85151A819B117CA1FF6597\ +F6156E80FDD28C9C3176835164D37DA7DA11D94E09ADD770B68A6E081CD22CA0\ +C004BFE7CD283BF43A588DA91F509B27A6584C474A4A2F3EE0F1F56447379240\ +A5AB1FB77FDCA49B305F07BA86B62756FB9EFB4FC225C86845F026EA542076B9\ +1A0BC2CDD136E122C659BE259D98E5841DF4C2F60330D4D8CDEE7BF1A0A24452\ +4EECC68FF2AEF5BF0069C9E87A11C6E519DE1A4062A10C83837388F7EF58598A\ +3846F49D499682B683C4A062B421594FAFBC1383C943BA83BDEF515EFCF10D:\ +B8098CB26FCC5ACD64C492919EA1C7ECDC9B3DE4854D69E7947E05BD0BF6E84C\ +240FA83ACEE02C829A959614107CE03DB8ACA40D38F9CC57B7F94C3C220DEEEB + +47B8216AA0FBB5D67966F2E82C17C07AA2D6327E96FCD83E3DE7333689F3EE79\ +994A1BF45082C4D725ED8D41205CB5BCDF5C341F77FACB1DA46A5B9B2CBC49EA\ +DF786BCD881F371A95FA17DF73F606519AEA0FF79D5A11427B98EE7F13A5C006\ +37E2854134691059839121FEA9ABE2CD1BCBBBF27C74CAF3678E05BFB1C94989\ +7EA01F56FFA4DAFBE8644611685C617A3206C7A7036E4AC816799F693DAFE7F1\ +9F303CE4EBA09D21E03610201BFC665B72400A547A1E00FA9B7AD8D84F84B34A\ +EF118515E74DEF11B9188BD1E1F97D9A12C30132EC2806339BDADACDA2FD8B78:\ +0F4C4ECFD9A8431D5AB9A245A77CD70974FB75F1824FE68583E9F25E73BA5725\ +88AD0C328D73BEBEDF1FC99D898B7D1C9EB9AB048896CD0446A3E932A97710AB + +8CFF1F67FE53C098896D9136389BD8881816CCAB34862BB67A656E3D98896F3C\ +E6FFD4DA73975809FCDF9666760D6E561C55238B205D8049C1CEDEEF374D1735\ +DAA533147BFA960B2CCE4A4F254176BB4D1BD1E89654432B8DBE1A135C42115B\ +394B024856A2A83DC85D6782BE4B444239567CCEC4B184D4548EAE3FF6A192F3\ +43292BA2E32A0F267F31CC26719EB85245D415FB897AC2DA433EE91A99424C9D\ +7F1766A44171D1651001C38FC79294ACCC68CEB5665D36218454D3BA169AE058\ +A831338C17743603F81EE173BFC0927464F9BD728DEE94C6AEAB7AAE6EE3A627\ +E8:\ +C90025BE7F02FA18134B63681B5A635A51C06EE37878C4833E0A853FA474AEFD\ +06BEEBA4597ED8E59255EE4DEC81B34D6EF3DF617A885F50B79F6EF9E47B4003 + +EACD07971CFF9B9939903F8C1D8CBB5D4DB1B548A85D04E037514A583604E787\ +F32992BF2111B97AC5E8A938233552731321522AB5E8583561260B7D13EBEEF7\ +85B23A41FD8576A6DA764A8ED6D822D4957A545D5244756C18AA80E1AAD4D1F9\ +C20D259DEE1711E2CC8FD013169FB7CC4CE38B362F8E0936AE9198B7E838DCEA\ +4F7A5B9429BB3F6BBCF2DC92565E3676C1C5E6EB3DD2A0F86AA23EDD3D0891F1\ +97447692794B3DFA269611AD97F72B795602B4FDB198F3FD3EB41B415064256E\ +345E8D8C51C555DC8A21904A9B0F1AD0EFFAB7786AAC2DA3B196507E9F33CA35\ +6427:\ +5C21E22D8B2887134F03D05945D91282B6321F122E53640C046FF9B1692F1210\ +CA46CD8471E95F3C74F7FEB1DA0DC8A421EEFFB3699351825F16BA621015EEEF + +23AC4E9A42C6EF45C3336CE6DFC2FF7DE8884CD23DC912FEF0F7756C09D335C1\ +89F3AD3A23697ABDA851A81881A0C8CCAFC980AB2C702564C2BE15FE4C4B9F10\ +DFB2248D0D0CB2E2887FD4598A1D4ACDA897944A2FFC580FF92719C95CF2AA42\ +DC584674CB5A9BC5765B9D6DDF5789791D15F8DD925AA12BFFAFBCE60827B490\ +BB7DF3DDA6F2A143C8BF96ABC903D83D59A791E2D62814A89B8080A28060568C\ +F24A80AE61179FE84E0FFAD00388178CB6A617D37EFD54CC01970A4A41D1A8D3\ +DDCE46EDBBA4AB7C90AD565398D376F431189CE8C1C33E132FEAE6A8CD17A61C\ +630012:\ +F1A7011447E8515E1502A3AE56F8BE61EB4200BC4D21C8E1875B73AB2A42DE46\ +13D6404B17A740B60B57F742C92F45C07880498C44C989C15CF1CD37B3F26E77 + +0172DF732282C9D488669C358E3492260CBE91C95CFBC1E3FEA6C4B0EC129B45\ +F242ACE09F152FC6234E1BEE8AAB8CD56E8B486E1DCBA9C05407C2F95DA8D8F1\ +C0AF78EE2ED82A3A79EC0CB0709396EE62AADB84F8A4EE8A7CCCA3C1EE84E302\ +A09EA802204AFECF04097E67D0F8E8A9D2651126C0A598A37081E42D168B0AE8\ +A71951C524259E4E2054E535B779679BDADE566FE55700858618E626B4A0FAF8\ +95BCCE9011504A49E05FD56127EAE3D1F8917AFB548ECADABDA1020111FEC931\ +4C413498A360B08640549A22CB23C731ACE743252A8227A0D2689D4C60016066\ +78DFB921:\ +02BE97BE60F581D73527490734CD5F8739DCB9A5089CC49C7619277CEB30D9A6\ +9B85C53EFC55C780A6494DD172B8BEB2B69F86DD4B7CBFA3E47F1720ED394383 + +3875B9240CF3E0A8B59C658540F26A701CF188496E2C2174788B126FD29402D6\ +A75453BA0635284D08835F40051A2A9683DC92AFB9383719191231170379BA6F\ +4ADC816FECBB0F9C446B785BF520796841E58878B73C58D3EBB097CE4761FDEA\ +BE15DE2F319DFBAF1742CDEB389559C788131A6793E193856661376C81CE9568\ +DA19AA6925B47FFD77A43C7A0E758C37D69254909FF0FBD415EF8EB937BCD49F\ +91468B49974C07DC819ABD67395DB0E05874FF83DDDAB895344ABD0E7111B2DF\ +9E58D76D85AD98106B36295826BE04D435615595605E4B4BB824B33C4AFEB5E7\ +BB0D19F909:\ +38652A2D6674A539559F3ED0996542C23D48D8D108C2AF9C10DA45C9DBC11906\ +CB4AEE8EB04C88789B763C66B743356336C8950303B950D72A8FCA05B9C67CD9 + +747CC1A59FEFBA94A9C75BA866C30DC5C1CB0C0F8E9361D98484956DD5D1A40F\ +6184AFBE3DAC9F76028D1CAECCFBF69199C6CE2B4C092A3F4D2A56FE5A33A007\ +57F4D7DEE5DFB0524311A97AE0668A47971B95766E2F6DD48C3F57841F91F04A\ +00AD5EA70F2D479A2620DC5CD78EAAB3A3B011719B7E78D19DDF70D9423798AF\ +77517EBC55392FCD01FC600D8D466B9E7A7A85BF33F9CC5419E9BD874DDFD609\ +81150DDAF8D7FEBAA4374F0872A5628D318000311E2F5655365AD4D407C20E5C\ +04DF17A222E7DEEC79C5AB1116D8572F91CD06E1CCC7CED53736FC867FD49ECE\ +BE6BF8082E8A:\ +BC091874BAF2195324C56EE8386E13AC3F49FDB329C2D5835848AF2A3653BCEA\ +26EC8C370912CBCFB1C20D3EB9AB53C6160CDD5351836527C5719084A575EF64 + +57AF971FCCAEC97435DC2EC9EF0429BCEDC6B647729EA168858A6E49AC1071E7\ +06F4A5A645CA14E8C7746D65511620682C906C8B86EC901F3DDED4167B3F00B0\ +6CBFAC6AEE3728051B3E5FF10B4F9ED8BD0B8DA94303C833755B3CA3AEDDF0B5\ +4BC8D6632138B5D25BAB03D17B3458A9D782108006F5BB7DE75B5C0BA854B423\ +D8BB801E701E99DC4FEAAD59BC1C7112453B04D33EA3635639FB802C73C2B71D\ +58A56BBD671B18FE34ED2E3DCA38827D63FDB1D4FB3285405004B2B3E26081A8\ +FF08CD6D2B08F8E7B7E90A2AB1ED7A41B1D0128522C2F8BFF56A7FE67969422C\ +E839A9D4608F03:\ +D8025F57C003DDCC6ABDDCE2CCFFDB9C11BE984311A749A632D7EE4EB073C58F\ +0074096C17CE0A46B37700581D9FF074143F34322D5460C4BD1E9EE6AD497F40 + +04E16DEDC1227902BAAF332D3D08923601BDD64F573FAA1BB7201918CFE16B1E\ +10151DAE875DA0C0D63C59C3DD050C4C6A874011B018421AFC4623AB0381831B\ +2DA2A8BA42C96E4F70864AC44E106F94311051E74C77C1291BF5DB9539E69567\ +BF6A11CF6932BBBAD33F8946BF5814C066D851633D1A513510039B349939BFD4\ +2B858C21827C8FF05F1D09B1B0765DC78A135B5CA4DFBA0801BCADDFA175623C\ +8B647EACFB4444B85A44F73890607D06D507A4F8393658788669F6EF4DEB58D0\ +8C50CA0756D5E2F49D1A7AD73E0F0B3D3B5F090ACF622B1878C59133E4A848E0\ +5153592EA81C6FBF:\ +99812EB8737BF609B3BF4B8ADE116403183DD7332DAB4F43BB4917DA0B62ABC5\ +A4772D572BDDA22FD555AF55309D31FB93492ED3EF4455FDE4FFFE7BF8DF84AE + +7C815C384EEE0F288ECE27CCED52A01603127B079C007378BC5D1E6C5E9E6D1C\ +735723ACBBD5801AC49854B2B569D4472D33F40BBB8882956245C366DC3582D7\ +1696A97A4E19557E41E54DEE482A14229005F93AFD2C4A7D8614D10A97A9DFA0\ +7F7CD946FA45263063DDD29DB8F9E34DB60DAA32684F0072EA2A9426ECEBFA52\ +39FB67F29C18CBAA2AF6ED4BF4283936823AC1790164FEC5457A9CBA7C767CA5\ +9392D94CAB7448F50EB34E9A93A80027471CE59736F099C886DEA1AB4CBA4D89\ +F5FC7AE2F21CCD27F611ECA4626B2D08DC22382E92C1EFB2F6AFDC8FDC3D2172\ +604F5035C46B8197D3:\ +6B242888A6E956F10A8BE75E09287D59CC25155B0AA8D8BA02E095D0AFAA2910\ +4CB2051AA4B3430B724D500AD0317208C3BA9FB1265BF19A974E90F4BF0CE006 + +E29D505158DBDD937D9E3D2145658EE6F5992A2FC790F4F608D9CDB44A091D5B\ +94B88E81FAC4FDF5C49442F13B911C55886469629551189EAFF62488F1A479B7\ +DB11A1560E198DDCCCCF50159093425FF7F1CB8D1D1246D0978764087D6BAC25\ +7026B090EFAE8CEC5F22B6F21C59ACE1AC7386F5B8837CA6A12B6FBF5534DD05\ +60EF05CA78104D3B943DDB220FEAEC89AA5E692A00F822A2AB9A2FE60350D75E\ +7BE16FF2526DC643872502D01F42F188ABED0A6E9A6F5FD0D1CE7D5755C9FFA6\ +6B0AF0B20BD806F08E06156690D81AC811778CA3DAC2C249B96002017FCE93E5\ +07E3B953ACF99964B847:\ +FF77EF8DE1483F8A498E3554083BB69F7567FCED495E6BF0C9902CDCB5247FAC\ +6A4B50D1CF9CEE89C400ED3E4E6FEBB642F1AC3BBD018ECC04CB1A43A1331ECC + +D85588696F576E65ECA0155F395F0CFACD83F36A99111ED5768DF2D116D2121E\ +32357BA4F54EDE927F189F297D3A97FAD4E9A0F5B41D8D89DD7FE20156799C2B\ +7B6BF9C957BA0D6763F5C3BC5129747BBB53652B49290CFF1C87E2CDF2C4B95D\ +8AAEE09BC8FBFA6883E62D237885810491BFC101F1D8C636E3D0EDE838AD05C2\ +07A3DF4FAD76452979EB99F29AFAECEDD1C63B8D36CF378454A1BB67A741C77A\ +C6B6B3F95F4F02B64DABC15438613EA49750DF42EE90101F115AA9ABB9FF6432\ +4DDE9DABBB01054E1BD6B4BCDC7930A44C2300D87CA78C06924D0323AD7887E4\ +6C90E8C4D100ACD9EED21E:\ +83E0BEDD263922F016CF539F9E7B43ACAFDDF35C8CE730434EE3E92ACD264006\ +031073A705F5585BFB66E53EA6A733901AE40634B6F4D86FB554CE0EBC5CD807 + +3A12F8508B40C32C74492B66323375DCFE49184C78F73179F3314B79E63376B8\ +AC683F5A51F1534BD729B02B04D002F55CBD8E8FC9B5EC1EA6BBE6A0D0E74315\ +18E6BA45D124035F9D3DCE0A8BB7BF1430A9F657E0B4EA9F20EB20C786A58181\ +A1E20A96F1628F8728A13BDF7A4B4B32FC8AA7054CC4881AE7FA19AFA65C6C3E\ +E1B3ADE3192AF42054A8A911B8EC1826865D46D93F1E7C5E2B7813C92A506E53\ +886F3D4701BB93D2A681AD109C845904BB861AF8AF0646B6E399B38B614051D3\ +4F6842563A0F37EC00CB3D865FC5D746C4987DE2A65071100883A2A9C7A2BFE1\ +E2DD603D9EA24DC7C5FD06BE:\ +E063490AC5C915BAF98C37660EB17A85798D728FB57CB0ACFAEDE8AFE847C902\ +5D8BF55B6EEA096A6F0B443B38D0BC77DD0BCB8228ED2681BB03A013D15CEB79 + +1861EDCE46FA5AD17E1FF1DEAE084DEC580F97D0A67885DFE834B9DFAC1AE076\ +742CE9E267512CA51F6DF5A455AF0C5FD6ABF94ACEA103A3370C354485A7846F\ +B84F3AC7C2904B5B2FBF227002CE512133BB7E1C4E50057BFD1E44DB33C7CDB9\ +69A99E284B184F50A14B068A1FC5009D9B298DBE92239572A7627AAC02ABE8F3\ +E3B473417F36D4D2505D16B7577F4526C9D94A270A2DFE450D06DA8F6FA95687\ +9A0A55CFE99E742EA555EA477BA3E9B44CCD508C375423611AF92E55345DC215\ +779B2D5119EBA49C71D49B9FE3F1569FA24E5CA3E332D042422A8B8158D3EC66\ +A80012976F31FFDF305F0C9C5E:\ +2F2FBA371016CD20ADC35C032B61100C298FBAF81506E83CC6E9BCC61244838A\ +D83465658A6436BD488C55D27B82BA3FFC5223BB97A03AE33E05CA750FDF56E2 + +08D0FFDE3A6E4EF65608EA672E4830C12943D7187CCFF08F4941CFC13E545F3B\ +9C7AD5EEBBE2B01642B486CAF855C2C73F58C1E4E3391DA8E2D63D96E15FD849\ +53AE5C231911B00AD6050CD7AAFDAAC9B0F663AE6AAB45519D0F5391A541707D\ +479034E73A6AD805AE3598096AF078F1393301493D663DD71F83869CA27BA508\ +B7E91E81E128C1716DC3ACFE3084B2201E04CF8006617EECF1B640474A5D45CF\ +DE9F4D3EF92D6D055B909892194D8A8218DB6D8203A84261D200D71473D7488F\ +3427416B6896C137D455F231071CACBC86E0415AB88AEC841D96B7B8AF41E05B\ +B461A40645BF176601F1E760DE5F:\ +783AF05873F418BAF09AA3479FFBA6CC9949F90D7CB9DF1355B46B020712EDD4\ +0477F7B2980DEFC4474B2D3C24BF92ECB5DA64FBDF167EDD9D9D48792D2B4DF8 + +D782ABB72A5BE3392757BE02D3E45BE6E2099D6F000D042C8A543F50ED6EBC05\ +5A7F133B0DD8E9BC348536EDCAAE2E12EC18E8837DF7A1B3C87EC46D50C241DE\ +E820FD586197552DC20BEEA50F445A07A38F1768A39E2B2FF05DDDEDF751F1DE\ +F612D2E4D810DAA3A0CC904516F9A43AF660315385178A529E51F8AAE141808C\ +8BC5D7B60CAC26BB984AC1890D0436EF780426C547E94A7B08F01ACBFC4A3825\ +EAE04F520A9016F2FB8BF5165ED12736FC71E36A49A73614739EAA3EC834069B\ +1B40F1350C2B3AB885C02C640B9F7686ED5F99527E41CFCD796FE4C256C91731\ +86C226169FF257954EBDA81C0E5F99:\ +B53D11E8514950F60345F266290DFD57B8550C011F2BBC1C7CD718E74CAA9847\ +3E98CF794975661C7D46D6DF10E14F0AF2E0EFBD480A350AC60E0881EA7090FD + +5FCE8109A358570E40983E1184E541833BB9091E280F258CFB144387B05D190E\ +431CB19BAA67273BA0C58ABE91308E1844DCD0B3678BAA42F335F2FA05267A02\ +40B3C718A5942B3B3E3BFA98A55C25A1466E8D7A603722CB2BBF03AFA54CD769\ +A99F310735EE5A05DAE2C22D397BD95635F58C48A67F90E1B73AAFCD3F82117F\ +0166657838691005B18DA6F341D6E90FC1CDB352B30FAE45D348294E501B6325\ +2DE14740F2B85AE5299DDEC3172DE8B6D0BA219A20A23BB5E10FF434D39DB3F5\ +83305E9F5C039D98569E377B75A70AB837D1DF269B8A4B566F40BB91B577455F\ +D3C356C914FA06B9A7CE24C7317A172D:\ +0E21302B185191492D2625F0FC4A3380ECD75D8EA945E35FD6E57EB7142DE249\ +90EEE2B6711392F8856874DE50E6D2FDF1D23A228877298C668251FD0F06B709 + +6172F1971A6E1E4E6170AFBAD95D5FEC99BF69B24B674BC17DD78011615E502D\ +E6F56B86B1A71D3F4348087218AC7B7D09302993BE272E4A591968AEF18A1262\ +D665610D1070EE91CC8DA36E1F841A69A7A682C580E836941D21D909A3AFC1F0\ +B963E1CA5AB193E124A1A53DF1C587470E5881FB54DAE1B0D840F0C8F9D1B04C\ +645BA1041C7D8DBF22030A623AA15638B3D99A2C400FF76F3252079AF88D2B37\ +F35EE66C1AD7801A28D3D388AC450B97D5F0F79E4541755356B3B1A5696B023F\ +39AB7AB5F28DF4202936BC97393B93BC915CB159EA1BD7A0A414CB4B7A1AC3AF\ +68F50D79F0C9C7314E750F7D02FAA58BFA:\ +1A77E749C8249D06F08943F5CDFEB5D65C804F1052B036CCD7A6F16120315AF7\ +B20C6BE56CA65861A2568F7E726420E909FAF47E4ED96A3C299AFF94EDFBF6EB + +5668ECD99DFBE215C4118398AC9C9EAF1A1433FAB4CCDD3968064752B625EA94\ +4731F75D48A27D047D67547F14DD0FFAA55FA5E29F7AF0D161D85EAFC4F2029B\ +717C918EAB9D304543290BDBA7158B68020C0BA4E079BC95B5BC0FC044A992B9\ +4B4CCD3BD66D0EABB5DBBAB904D62E00752C4E3B0091D773BCF4C14B4377DA3E\ +FFF824B1CB2FA01B32D1E46C909E626ED2DAE920F4C7DBEB635BC754FACBD8D4\ +9BEBA3F23C1C41CCBFCD0EE0C114E69737F5597C0BF1D859F0C767E18002AE8E\ +39C26261FFDE2920D3D0BAF0E906138696CFE5B7E32B600F45DF3AAA39932F3A\ +7DF95B60FA8712A2271FCAF3911CE7B511B1:\ +CDF5CC029A5946BB96A524D865C6BAB024A2B598A9A657EF631FA582ED9BEBF5\ +6C18D955528A3DD5BC0D2466F7EE0EF8AF1C814E3858E5DA3A2BA951BB2D79A0 + +03D625488354DF30E3F875A68EDFCF340E8366A8E1AB67F9D5C5486A96829DFA\ +C0578289082B2A62117E1CF418B43B90E0ADC881FC6AE8105C888E9ECD21AEA1\ +C9AE1A4038DFD17378FED71D02AE492087D7CDCD98F746855227967CB1AB4714\ +261EE3BEAD3F4DB118329D3EBEF4BC48A875C19BA763966DA0EBEA800E01B2F5\ +0B00E9DD4CACA6DCB314D00184EF71EA2391D760C950710DB4A70F9212FFC548\ +61F9DC752CE18867B8AD0C48DF8466EF7231E7AC567F0EB55099E622EBB86CB2\ +37520190A61C66AD34F1F4E289CB3282AE3EAAC6152ED24D2C92BAE5A7658252\ +A53C49B7B02DFE54FDB2E90074B6CF310AC661:\ +2A4B61FEAAC1BC466DD77EBE6E800F87950B28532F71BE5E4D56DE28F93C1F7E\ +61C793745A91B8CCDC29914989730B7DF933E6C7F1B1A08638953F966F092560 + +2EDC282FFB90B97118DD03AAA03B145F363905E3CBD2D50ECD692B37BF000185\ +C651D3E9726C690D3773EC1E48510E42B17742B0B0377E7DE6B8F55E00A8A4DB\ +4740CEE6DB0830529DD19617501DC1E9359AA3BCF147E0A76B3AB70C4984C13E\ +339E6806BB35E683AF8527093670859F3D8A0FC7D493BCBA6BB12B5F65E71E70\ +5CA5D6C948D66ED3D730B26DB395B3447737C26FAD089AA0AD0E306CB28BF0AC\ +F106F89AF3745F0EC72D534968CCA543CD2CA50C94B1456743254E358C1317C0\ +7A07BF2B0ECA438A709367FAFC89A57239028FC5FECFD53B8EF958EF10EE0608\ +B7F5CB9923AD97058EC067700CC746C127A61EE3:\ +A40028E17CD5DA2DB800437A58861565E0A55CD3DC017FE48C7D3F2D4706D7EC\ +742A21170CB86B32B5B9A1496C5C5DDE4E283915BFCDC883F08039679E29ED43 + +90B28A6AA1FE533915BCB8E81ED6CACDC10962B7FF82474F845EEB86977600CF\ +70B07BA8E3796141EE340E3FCE842A38A50AFBE90301A3BDCC591F2E7D9DE53E\ +495525560B908C892439990A2CA2679C5539FFDF636777AD9C1CDEF809CDA9E8\ +DCDB451ABB9E9C17EFA4379ABD24B182BD981CAFC792640A183B61694301D04C\ +5B3EAAD694A6BD4CC06EF5DA8FA23B4FA2A64559C5A68397930079D250C51BCF\ +00E2B16A6C49171433B0AADFD80231276560B80458DD77089B7A1BBCC9E7E4B9\ +F881EACD6C92C4318348A13F4914EB27115A1CFC5D16D7FD94954C3532EFACA2\ +CAB025103B2D02C6FD71DA3A77F417D7932685888A:\ +2A1F1C7FAFBE676D2A7BC67BD80C9387F493643E2395852AF8A6846A5DDC191C\ +B17FCAA17BB82266FEA390B3E45DED4A15408A29DF5AE390A1BC945D5D97C1C7 + +2969447D175490F2AA9BB055014DBEF2E6854C95F8D60950BFE8C0BE8DE254C2\ +6B2D31B9E4DE9C68C9ADF49E4EE9B1C2850967F29F5D08738483B417BB96B2A5\ +6F0C8ACA632B552059C59AAC3F61F7B45C966B75F1D9931FF4E596406378CEE9\ +1AAA726A3A84C33F37E9CDBE626B5745A0B06064A8A8D56E53AAF102D23DD9DF\ +0A3FDF7A638509A6761A33FA42FA8DDBD8E16159C93008B53765019C3F0E9F10\ +B144CE2AC57F5D7297F9C9949E4FF68B70D339F87501CE8550B772F32C6DA8AD\ +2CE2100A895D8B08FA1EEAD7C376B407709703C510B50F87E73E43F8E7348F87\ +C3832A547EF2BBE5799ABEDCF5E1F372EA809233F006:\ +80C5090FDDA7FB8B550602FBB156D650958E0EE131E21C09FCCB57FAA9A9C868\ +C5947E409BC5CFA89C8616619E625C7D1DAD8686FF59C2CD1D9940E336472145 + +721645633A44A2C78B19024EAECF58575AB23C27190833C26875DC0F0D50B46A\ +EA9C343D82EA7D5B3E50EC700545C615DAEAEA64726A0F05607576DCD396D812\ +B03FB6551C641087856D050B10E6A4D5577B82A98AFB89CEE8594C9DC19E79FE\ +FF0382FCFD127F1B803A4B9946F4AC9A4378E1E6E041B1389A53E3450CD32D9D\ +2941B0CBABDB50DA8EA2513145164C3AB6BCBD251C448D2D4B087AC57A59C228\ +5D564F16DA4ED5E607ED979592146FFB0EF3F3DB308FB342DF5EB5924A48256F\ +C763141A278814C82D6D6348577545870AE3A83C7230AC02A1540FE1798F7EF0\ +9E335A865A2AE0949B21E4F748FB8A51F44750E213A8FB:\ +A779BC3D4F6315BEFDA9CBBBDBA4C9E24D810CB46074D81A6E2D66947A30F62C\ +4D3EB92AFC6D9BFBF42DF3D8528982FCF7AECA66740D0E753040A2C6F71AC1DB + +6B860D39725A14B498BB714574B4D37CA787404768F64C648B1751B353AC92BA\ +C2C3A28EA909FDF0423336401A02E63EC24325300D823B6864BB701F9D7C7A1F\ +8EC9D0AE3584AA6DD62EA1997CD831B4BABD9A4DA50932D4EFDA745C61E41308\ +90E156AEE6113716DAF95764222A91187DB2EFFEA49D5D0596102D619BD26A61\ +6BBFDA8335505FBB0D90B4C180D1A2335B91538E1668F9F9642790B4E55F9CAB\ +0FE2BDD2935D001EE6419ABAB5457880D0DBFF20ED8758F4C20FE759EFB33141\ +CF0E892587FE8187E5FBC57786B7E8B089612C936DFC03D27EFBBE7C8673F160\ +6BD51D5FF386F4A7AB68EDF59F385EB1291F117BFE717399:\ +46D64790833ABF3E17BB4B8CCDB4F0A2DCD23FDFA3135744306F4916A658CC5B\ +0BB60DD65DD2287287CA645C0B5904A7227ED1B40730A6F335BEC41706769E9D + +6A01830AF3889A25183244DECB508BD01253D5B508AB490D3124AFBF42626B2E\ +70894E9B562B288D0A2450CFACF14A0DDAE5C04716E5A0082C33981F6037D23D\ +5E045EE1EF2283FB8B6378A914C5D9441627A722C282FF452E25A7EA608D69CE\ +E4393A0725D17963D0342684F255496D8A18C2961145315130549311FC07F031\ +2FB78E6077334F87EAA873BEE8AA95698996EB21375EB2B4EF53C14401207DEB\ +4568398E5DD9A7CF97E8C9663E23334B46912F8344C19EFCF8C2BA6F04325F1A\ +27E062B62A58D0766FC6DB4D2C6A1928604B0175D872D16B7908EBC041761187\ +CC785526C2A3873FEAC3A642BB39F5351550AF9770C328AF7B:\ +29EBB2B1BF14463500B983F8C9FE9EAD506514E9AF11202A9E0930B225EBC525\ +8A09324010C52FF35E902647D9701293A8F8A007ABC3D6A7BE629C5078A42BED + +B3C5E74B69933C2533106C563B4CA20238F2B6E675E8681E34A389894785BDAD\ +E59652D4A73D80A5C85BD454FD1E9FFDAD1C3815F5038E9EF432AAC5C3C4FE84\ +0CC370CF86580A6011778BBEDAF511A51B56D1A2EB68394AA299E26DA9ADA6A2\ +F39B9FAFF7FBA457689B9C1A577B2A1E505FDF75C7A0A64B1DF81B3A356001BF\ +0DF4E02A1FC59F651C9D585EC6224BB279C6BEBA2966E8882D68376081B98746\ +8E7AED1EF90EBD090AE825795CDCA1B4F09A979C8DFC21A48D8A53CDBB26C4DB\ +547FC06EFE2F9850EDD2685A4661CB4911F165D4B63EF25B87D0A96D3DFF6AB0\ +758999AAD214D07BD4F133A6734FDE445FE474711B69A98F7E2B:\ +8DB46A5D23103103746C2FE2480CEEC56FD9796AD357F5BC45BF0BC2D2E8B95E\ +A0C286090AB858183C2A051B80FCA8776670FA3DA8722329848F057C6EAD4991 + +83AF34279CCB5430FEBEC07A81950D30F4B66F484826AFEE7456F0071A51E1BB\ +C55570B5CC7EC6F9309C17BF5BEFDD7C6BA6E968CF218A2B34BD5CF927AB846E\ +38A40BBD81759E9E33381016A755F699DF35D660007B5EADF292FEEFB735207E\ +BF70B5BD17834F7BFA0E16CB219AD4AF524AB1EA37334AA66435E5D397FC0A06\ +5C411EBBCE32C240B90476D307CE802EC82C1C49BC1BEC48C0675EC2A6C6F3ED\ +3E5B741D13437095707C565E10D8A20B8C20468FF9514FCF31B4249CD82DCEE5\ +8C0A2AF538B291A87E3390D737191A07484A5D3F3FB8C8F15CE056E5E5F8FEBE\ +5E1FB59D6740980AA06CA8A0C20F5712B4CDE5D032E92AB89F0AE1:\ +BC933D42AD3267F608AB201D2813E54250499D87ECEEF837863F59D8ACE4ED6A\ +3239C4C7CD7E172F3CF3CDED5D84950E066E2F549A767BA421CAD4A223313C1D + +A7ED84749CCC56BB1DFBA57119D279D412B8A986886D810F067AF349E8749E9E\ +A746A60B03742636C464FC1EE233ACC52C1983914692B64309EDFDF29F1AB912\ +EC3E8DA074D3F1D231511F5756F0B6EEAD3E89A6A88FE330A10FACE267BFFBFC\ +3E3090C7FD9A850561F363AD75EA881E7244F80FF55802D5EF7A1A4E7B89FCFA\ +80F16DF54D1B056EE637E6964B9E0FFD15B6196BDD7DB270C56B47251485348E\ +49813B4EB9ED122A01B3EA45AD5E1A929DF61D5C0F3E77E1FDC356B63883A60E\ +9CBB9FC3E00C2F32DBD469659883F690C6772E335F617BC33F161D6F6984252E\ +E12E62B6000AC5231E0C9BC65BE223D8DFD94C5004A101AF9FD6C0FB:\ +D84DDA22FBE020F57EFBC8C612B2F781EAA81E4C9B0F013BFC1B3C926A5BA778\ +28F8C6684A25B2C567DAD1B705E7BB417F5EAE6D8BD2BFA6ACBC7284F3C19E81 + +A6FE30DCFCDA1A329E82AB50E32B5F50EB25C873C5D2305860A835AECEE6264A\ +A36A47429922C4B8B3AFD00DA16035830EDB897831C4E7B00F2C23FC0B15FDC3\ +0D85FB70C30C431C638E1A25B51CAF1D7E8B050B7F89BFB30F59F0F20FECFF3D\ +639ABC4255B3868FC45DD81E47EB12AB40F2AAC735DF5D1DC1AD997CEFC4D836\ +B854CEE9AC02900036F3867FE0D84AFFF37BDE3308C2206C62C4743375094108\ +877C73B87B2546FE05EA137BEDFC06A2796274099A0D554DA8F7D7223A48CBF3\ +1B7DECAA1EBC8B145763E3673168C1B1B715C1CD99ECD3DDB238B06049885ECA\ +D9347C2436DFF32C771F34A38587A44A82C5D3D137A03CAA27E66C8FF6:\ +C4966858DB87DFC7DAE95CB51A8B19DD481F75B3FF554B18458C0F25A285F613\ +5D73FF6F1B498B957E8481F16612D8B52E187BDE76B3A8D1A6324A3899F056D8 + +83167FF53704C3AA19E9FB3303539759C46DD4091A52DDAE9AD86408B6933598\ +9E61414BC20AB4D01220E35241EFF5C9522B079FBA597674C8D716FE441E5661\ +10B6211531CECCF8FD06BC8E511D00785E57788ED9A1C5C73524F01830D2E114\ +8C92D0EDC97113E3B7B5CD3049627ABDB8B39DD4D6890E0EE91993F92B03354A\ +88F52251C546E64434D9C3D74544F23FB93E5A2D2F1FB15545B4E1367C97335B\ +0291944C8B730AD3D4789273FA44FB98D78A36C3C3764ABEEAC7C569C1E43A35\ +2E5B770C3504F87090DEE075A1C4C85C0C39CF421BDCC615F9EFF6CB4FE64680\ +04AECE5F30E1ECC6DB22AD9939BB2B0CCC96521DFBF4AE008B5B46BC006E:\ +DEF5B398B53E2B884AAA19D86186EC7B386974386B24F5C993417C1B3377449D\ +0EE19D00AB789E2D63A56B01101E44692815644147D1C2D66A9A68579BEB2B50 + +3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5\ +623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A\ +15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0\ +A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764\ +B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43\ +C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D\ +817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E08\ +5172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1:\ +59D674C09E78B40FADD298EE83FB2CB4468CA96AFAA75CE3F4B451C0D353C28A\ +632A0DE753800D49FDBD6EA190025C5340036910BDBACC91C2D988B6FB2F8789 + +724627916C50338643E6996F07877EAFD96BDF01DA7E991D4155B9BE1295EA7D\ +21C9391F4C4A41C75F77E5D27389253393725F1427F57914B273AB862B9E31DA\ +BCE506E558720520D33352D119F699E784F9E548FF91BC35CA14704212870982\ +0D69A8287EA3257857615EB0321270E94B84F446942765CE882B191FAEE7E1C8\ +7E0F0BD4E0CD8A927703524B559B769CA4ECE1F6DBF313FDCF67C572EC4185C1\ +A88E86EC11B6454B371980020F19633B6B95BD280E4FBCB0161E1A82470320CE\ +C6ECFA25AC73D09F1536F286D3F9DACAFB2CD1D0CE72D64D197F5C7520B3CCB2\ +FD74EB72664BA93853EF41EABF52F015DD591500D018DD162815CC993595B195:\ +7A3E81CDEA3E783B0D2E77373D7E3AD3E069DF3C9F16EA87E41CD7178EBA02D4\ +9AA344C562EA9DB6FB20645F5F3DB9B62EC1F18ADFB5C10C77C1EBACEECC5E25 + +3139840B8AD4BCD39092916FD9D01798FF5AA1E48F34702C72DFE74B12E98A11\ +4E318CDD2D47A9C320FFF908A8DBC2A5B1D87267C8E983829861A567558B37B2\ +92D4575E200DE9F1DE45755FAFF9EFAE34964E4336C259F1E66599A7C904EC02\ +539F1A8EAB8706E0B4F48F72FEC2794909EE4A7B092D6061C74481C9E21B9332\ +DC7C6E482D7F9CC3210B38A6F88F7918C2D8C55E64A428CE2B68FD07AB572A8B\ +0A2388664F99489F04EB54DF1376271810E0E7BCE396F52807710E0DEA94EB49\ +F4B367271260C3456B9818FC7A72234E6BF2205FF6A36546205015EBD7D8C252\ +7AA430F58E0E8AC97A7B6B793CD403D517D66295F37A34D0B7D2FA7BC345AC04\ +CA1E266480DEEC39F5C88641C9DC0BD1358158FDECDD96685BBBB5C1FE5EA89D\ +2CB4A9D5D12BB8C893281FF38E87D6B4841F0650092D447E013F20EA934E18:\ +B26C758C740DA514E7BE7966C2E371F96C263796688A771A955005D907AF23D1\ +9C47FB0FF920CA3DEF21E13B4C827E4AD586DBC3D28F3576DBC6694F48E8BC37 + +023D91AC532601C7CA3942D62827566D9268BB4276FCAA1AE927693A69616526\ +76DBA09219A01B3D5ADFA12547A946E78F3C5C62DD880B02D2EEEB4B96636529\ +C6B01120B23EFC49CCFB36B8497CD19767B53710A636683BC5E0E5C9534CFC00\ +4691E87D1BEE39B86B953572927BD668620EAB87836D9F3F8F28ACE41150776C\ +0BC6657178EBF297FE1F7214EDD9F215FFB491B681B06AC2032D35E6FDF832A8\ +B06056DA70D77F1E9B4D26AE712D8523C86F79250718405F91B0A87C725F2D3F\ +52088965F887D8CF87206DFDE422386E58EDDA34DDE2783B3049B86917B46280\ +27A05D4D1F429D2B49C4B1C898DDDCB82F343E145596DE11A54182F39F4718EC\ +AE8F506BD9739F5CD5D5686D7FEFC834514CD1B2C91C33B381B45E2E5335D7A8\ +720A8F17AFC8C2CB2BD88B14AA2DCA099B00AA575D0A0CCF099CDEC4870FB710\ +D2680E60C48BFC291FF0CEF2EEBF9B36902E9FBA8C889BF6B4B9F5CE53A19B0D\ +9399CD19D61BD08C0C2EC25E099959848E6A550CA7137B63F43138D7B651:\ +919998132C03BB57E2748C5715C4D3CCD72250633983A61174E5A9B53BFD3ED7\ +FA7BA8698BDF766B31B29E387B1E44E1C10402C3A9F4FCE845865803F805CB18 + +20FF454369A5D05B81A78F3DB05819FEA9B08C2384F75CB0AB6AA115DD690DA3\ +131874A1CA8F708AD1519EA952C1E249CB540D196392C79E87755424FEE7C890\ +808C562722359EEA52E8A12FBBB969DD7961D2BA52037493755A5FA04F0D50A1\ +AA26C9B44148C0D3B94D1C4A59A31ACA15AE8BD44ACB7833D8E91C4B86FA3135\ +A423387B8151B4133ED23F6D7187B50EC2204AD901AD74D396E44274E0ECAFAA\ +E17B3B9085E22260B35CA53B15CC52ABBA758AF6798FBD04ECEECED648F3AF4F\ +DB3DED7557A9A5CFB7382612A8A8F3F45947D1A29CE29072928EC193CA25D510\ +71BD5E1984ECF402F306EA762F0F25282F5296D997658BE3F983696FFA6D095C\ +6369B4DAF79E9A5D3136229128F8EB63C12B9E9FA78AFF7A3E9E19A62022493C\ +D136DEFBB5BB7BA1B938F367FD2F63EB5CA76C0B0FF21B9E36C3F07230CF3C30\ +74E5DA587040A76975D7E39F4494ACE5486FCBF380AB7558C4FE89656335B82E\ +4DB8659509EAB46A19613126E594042732DD4C411F41AA8CDEAC71C0FB40A94E\ +6DA558C05E77B6182806F26D9AFDF3DA00C69419222C8186A6EFAD600B410E6C\ +E2F2A797E49DC1F135319801FA6F396B06F975E2A190A023E474B618E7:\ +F0EECEC5514F8001BD7AF333B78AE40E0D20944AAA2710EB3524236ABE3EAF3C\ +999DB788869647B5737B60FD4BE4753722C2CA6E905E030EFD04749BA46251A5 + +4FBDC596508D24A2A0010E140980B809FB9C6D55EC75125891DD985D37665BD8\ +0F9BEB6A50207588ABF3CEEE8C77CD8A5AD48A9E0AA074ED388738362496D2FB\ +2C87543BB3349EA64997CE3E7B424EA92D122F57DBB0855A803058437FE08AFB\ +0C8B5E7179B9044BBF4D81A7163B3139E30888B536B0F957EFF99A7162F4CA5A\ +A756A4A982DFADBF31EF255083C4B5C6C1B99A107D7D3AFFFDB89147C2CC4C9A\ +2643F478E5E2D393AEA37B4C7CB4B5E97DADCF16B6B50AAE0F3B549ECE47746D\ +B6CE6F67DD4406CD4E75595D5103D13F9DFA79372924D328F8DD1FCBEB5A8E2E\ +8BF4C76DE08E3FC46AA021F989C49329C7ACAC5A688556D7BCBCB2A5D4BE69D3\ +284E9C40EC4838EE8592120CE20A0B635ECADAA84FD5690509F54F77E35A417C\ +584648BC9839B974E07BFAB0038E90295D0B13902530A830D1C2BDD53F1F9C9F\ +AED43CA4EED0A8DD761BC7EDBDDA28A287C60CD42AF5F9C758E5C7250231C09A\ +582563689AFC65E2B79A7A2B68200667752E9101746F03184E2399E4ED8835CB\ +8E9AE90E296AF220AE234259FE0BD0BCC60F7A4A5FF3F70C5ED4DE9C8C519A10\ +E962F673C82C5E9351786A8A3BFD570031857BD4C87F4FCA31ED4D50E14F2107\ +DA02CB5058700B74EA241A8B41D78461658F1B2B90BFD84A4C2C9D6543861AB3\ +C56451757DCFB9BA60333488DBDD02D601B41AAE317CA7474EB6E6DD:\ +E57A285664BF66D2D2C7F8AAB8B75224A793C799D16A4774BC0C8693976F33E3\ +10979C84FDC302822542581BAC488F68CA0987E7147A782B036DD211DC798408 + +D1890B4704E169C28E44DDF62A1091450404910539FC2DAEB26E8ACF4533B024\ +E5215C2D02820DD8FB2CFC1743955CBACFF0F8F35DFBB5E3F942F36247F68211\ +D518F3F601AAE12A1CDC000BAB43D4C973F287E80741DD1FCF6C34F2E6B4B6C3\ +13D01C4FF3CBF9166F26946F18EF2D58271BA9233F09A6B77BFD4F48B36EB3D7\ +3D1133C4F842A7DC3907F680B0B773242C11E3DD973A44327EA7CEA9C0F8E07D\ +682B6651E506B587559FE01ED721000BAF570A16FBDD9EA29FA3DEF4BE912058\ +321A8B720C5C102E48A6E7ED6F8838D400DD57D06EEDBCD15323F86D855C94B2\ +1E41B14EC9E1BBC8019211FD88138C91F9ABBD9BB3914D26C1DDC21673D2D512\ +63B39D66E741D924CF2B192C5D2C1A140126A3D64A2C77BE6C2C6EBE8599978A\ +E90BD36CBB9AF64D078910C4094AB3BF399C34F2AB8EF843E9FE1BF88BF443BA\ +21E4377E5F49C07FD9653B526E14562237F02D11B904BCA6AC31AE721A43E3C4\ +910A24AF6F4D80C031C109FC0FE49F15274BCA92BDA04C3B4196C192F6CE489C\ +63A806ACFC895AB52CAD657C1783B528E12D0ED856E1F8FC91F2AAFDFA0A9249\ +8D68530772EE73B359FCF1418D1096C46B34DCF90E5B468BBB2970BECBD70089\ +CFB039D64CC50FFF5EEF26384D34F24515A6558B06A1FDD88F1050C5BD78CC6E\ +D83D4C2B0E882AEBCF84AFB0430D0BF09F2FB42B8B4589158093A7709AAE75A7\ +90910E211EE1333FFB6FD80778DA3BF73858978E9DD647978841B18001DBAAEA\ +43CA0C0A03DBB9BCF30CE76A6F4B2CF2A9B6531B3E4051E7E05090CD421BC66C\ +4731E7122AD129FC42DEDC83BB460E3F889992FBD3CA072686E56B72C720FBC9\ +8D723EF7F247286F77CCDDC728738E941B1A74D4F16671C21FDD5643A115DDBC\ +B88EE7EC67EA66FD2BCE718DF6E085D4B5FC71A72696636A8F7B3A68AFA51A89\ +6771FAAA7F1F827430AC5E8089DBC0D4175E1B22A057BC5F1724EADC1A41E78F\ +A3ACAA8B97E5F2E19EF9D59AE12B04E7F0E8A621E098A66910E2A5ED2102B824\ +CD3EA044A854F1CD0B33E61E7F737414B2953549F25DD34D19AA1981DE7CD564\ +9FF6C6364A4F25312EF62395A747AB88AAD722C05AEC40DEEA8EEE5E779EF458\ +A68840BC6BD5D29AD40F98B3AE010B6213372ABB7BB8B8:\ +53BCB0FD89D9CF4A3738A01154D2B280F03B1D68EF7B512F6C657A0264488CA1\ +093D70F88C08DFE60CD418E938D74FE18EB3D525CD0492C8BF85FD2B2709516A + +4FA3DF1DEA75AD4B9C379206A95FED930000482E5B683FD2B17DC8E7D5C4BC1B\ +73186CCC13C9FF2DD09FC1D4F68034D120E84CA73A00B71A3B46D1EFC6FF88CF\ +2EDA65810B098CC5E651D9CF064E87076D5A871849F3B405D3D58EF5B1F10520\ +A9FB4FC84A81A87B13DBFBF9D8674943E28C257E46D8AD7BE1785F1DC7C9B1BD\ +574AD1DDA48F0255C853D2490BD3D63DA22A8369CFD02594999A2EF443308FB8\ +298266A11EFA177102C75DC674E89FC9DCC1A0D3C863BC26141102175D2678EB\ +6E13D90BBD9A5EB89AE8C0CB47D7F340D3D32042A2762BC9BF2B40EB40E87FB4\ +2610FE7E357051F01494704FBFF73321B47301A0799B7EE3FE5E62200F397A61\ +ED4509A62F7106ED0EFB0ABD6AE9E4A1FE9B02C092DCDC75015CF602F3B9A898\ +8B609E6C0D1C5C3E219FF57875C2EF01615F89447EA602DFC94EEC17A398C014\ +BD346691FE209A002771DC8164422CD166AFB457A8B3071282178A3EBD201D9B\ +07B27E711E7EE7D33AA5210ED4E4E92486775D14A6CED092E34A7AC826709399\ +48FEC149F9C018FCAAD3FC597D315713F44FC5E1725F448ECAED40E8D841BD02\ +F1E81C019B08F99412E360C0BD378391C67D964B47F50C26F0A483ED66402361\ +6B0FC9AFE43620DBE9CCFE070EF295C049EAC754C2123130C6B2C0232F6403AA\ +7F0DC35A5999BF95D34AD612234C6289277ADB60E4F72EC2DF570F05395B3BE8\ +A0A3C78B732821AA08927C524E15D65F66A3DB8C1C96FB70BC0686AAC310051F\ +469FC5EF880C0F66947C1C328F97684EA24CBE63BAED8D114F40507C2901034E\ +6AB3893F366D53F1CFCA309309218CABCECA4722FA9CCBC7249B87C12FF8397F\ +40487EB00082E7F551D27E301C3BC7B5389F7042534BF7E692DFEA4DA24F7C34\ +B8D2FF145F54B517FC97134EC5AC2CB925C508D7A6BD01FE7B764648274972BF\ +08560D30802E0EB7EDCC57AF4797BBF92E8688268606B0F1BC901FCC22136281\ +665EC16393FA9601C4FBDB18CD1D1EE382BC07973903E91FFA87399D1141D49F\ +4F0C064ACF3AC9897891DF10BCA0116F2C3FEF180FE6A8E937C478F2EF293AE9\ +186DCB1F76B6E48101DF64E57EA7C64C5C0025E221C8F5CBA5CC92D9CEC62814\ +0996B26D17F439B780F59A999301122F82D0495F8AB5AE1EA5790F45E992DFE0\ +0D5F82A7FF1354AEFDCEFC0D2D1731D22FA2B75AFD4FDA25AB194055FA962838\ +1055247C8C7587D22E73C60136C4282452D47AE03AA035FEBC26FCCD42A1CB79\ +CF866DB6418A49FD8261E877DDBB839CC39514DDB87A8A40D795532626FEA4A4\ +C35D13E028F9ED1BC09B06BE999B8DDD2258AA0596BCBBF72AF67E10BEDD58D5\ +99B8D577A583D676BF5561F80CE5E9528729A92DF578FE75DBC70474B75747A8\ +D55DE70E57BDD62D4344DC2115ED4DD62F1FC98BFA1E7421FC0700025C46D0ED\ +1BEF35C3B778563211B9FA9E8BA4BBCBF01C2FB626AB7EF325CE9F468DF2CACD\ +B178D36557CD85D542C067C289E926C1EA2F20ABD329E984168BB6DEF1DDCCF2\ +14DCB6A53AFD462F0E7E7A19E8C88F049244125A6D7DD41E58BC9B2FF7FA2478\ +DF76AF73090CB1AB59E388BA20E2C297C967737A1AF61793B68ECD7439444C48\ +E28E2D09C48FADA5E0D1D15E5B340A52F8B3B854CCA479F0A598445E14F53B3B\ +A36891050C79673DF3E2B5825C955A29E5C9A22F3991D0AA785718CFEA1D2385\ +F8E47E4A75ACBC7988D0558D541D71C4E6C5F1CB15B60CEA0C34A67BBCE105D7\ +A896025E0254DE7D7AF724C9027D44B8642192A08AB8E1EF3046DDA6014DF7F4\ +C9E63C635E48AB2E70B640D480998EC9357E665F99D76FE5529EF23C1BDFE017\ +C3A66CD4EB2DDB42EF85EA0CD65534:\ +6A6ACBD03B4A2CF63356C7B40B1C11B4E407349F13BE2A5EE0162D511B053760\ +CA9869B3036FE9D68475BFE3957B7007E0380F174B2CEC30ADD94DB65E43B4D0 + +523DE8B1F4CBB65E81FF0B6CCD6EB8EF0A0F0A691ACAF4A77F25ACD2D66AD4B3\ +EFD25BE70308853C094412A518A32020E3020A9F6AB32F0CD60EC0D7A194917D\ +6C457B168A54A4B46F7B0D0C71BD61CD202F4C718776A701E0770B0EFA054187\ +70F98E4E79CD066366FB3300E8BE359A98B82B764BC2FBBF59C7E8F94A157B01\ +C6C7577B1428138CD422BC47330F8ED99F4C0AAB0D984287445539839389EE08\ +D6345108AF26ADED0EC1D7BE774CFB8C5205DFE07CF6CAF8C1AFE37C7A2E4FE6\ +013B93EB2463DE4E0971C7178D6A76B16A0E8960C984CE8BBE71B3B466EDF044\ +5B835F09414D01F14C7B6167FF78FF118127BBD5F812C27FACD57B3B120E2BCF\ +E87315C7A92B82EF5D50CA14A7174D1BEA7E056523E055A6AE42EA3765094E55\ +44E5ED003C989C2F98F38A17E3DDA74DBAF9C669A319638A2698B0E4A611480D\ +8AD3CF016792ECD1034925F42B9811A7214D623D047ABCA31997DDEB03275F80\ +DD21F40DDC80616E7AD3D481E8EBC0A1A6A398E16A78369215541ED10B75671A\ +DEB1AAE6E11142A1CF665FC1B7332DFBB0E10C21A2B48F78E57319AC9C58DFA8\ +B1C2548E2979EF1ACCFEB215AFCD6C2C1B46FE97DD491758378330EFFC728366\ +1D2CB84FA05281E9E517408508D24D042E7B9BCD34DB87CE972E4CBCDB98615F\ +B93093369DFEDC782F44BCD03E81CF93051318B2401FF29F753A264BDA65AF19\ +9E3FCBB8B5D39C838A67D6C7A3DB046DC56C323DDBB5340CBC229E47CFF8C9D2\ +9B7A49AC0EC8C1440AE498C7D150EF91C29BEA7DF3EFCC2871A13A1D72D139CB\ +4603D9FFFE85F6DDD544850EF63C3944FB35DBC00D4308CEAA6394B6E23F650D\ +323F8F7EF50DDB68F1486EABF989BF44451F620EC9485C0B52D1415D3C909A2C\ +FBE9D77DB19D069D33BAEE4D77292E63FCBF65C1EBA24BFFDDEFE95211EF0AAF\ +8ABFDA9F94445E582976F986F5382CB669506AF2B4A5A0C43000A3C72C5CA4AA\ +CDC9D3D39FC5C492A393B6C341B86DACBBF6BA8B465100CC683EDB2D9B9F83ED\ +F9C6A32645F51CC79ADC22A52A007BAACA618BE35E356D1FD1CFBDA73F1ED092\ +53039DEF609450FD2D5943B9CD49CBD52A318EE3510D7CF3FD8FB388AC6CB9C6\ +EEFEF3D3CAD8501B91CC04A888D33E16D6A4C9666F5F5F3B257193F2B46DEDDE\ +11842909D8C48ADE57775B0B272E2DC9CEF1A083EB2CE58F4D1F211922FD6ADE\ +D1B82FE6F5B11251CD396E5A3666ED9626036E4E356231C146BBA0A91AFD3648\ +EB7BFE0B9C14F15AF2F92309826F468945CAD0AC422DE3D6A773B76178422107\ +CE0270E7F580B5CCEBA82CA0184AAFA8341141E65E39859885768FBC5CE63B96\ +5A0604B659E71D9DA2C7A43646088D8071D76926163AAFC69E25355BB0A222B7\ +B2DA9F0A20C021ADC462E905A9C3BF31C16D87FBEC3F014F3957A720F1432E17\ +41553092052FB58A198640479ABCAA51B104CC93E2636E1460643EA812BD44E8\ +19C2166EB6B349BA5BDEBAD59078910B5C22A56F004B8D9E4B1224D8D204B48A\ +BE7355548A402736C5CB110F3A1476ED631FF168F4F3EFD89B38DE4751536548\ +647523D334FAD7CC2D142973F2DB3C1FE08FC5CF83F9F2BD2DAA524B37864816\ +AF29EE05951FA09D1C51D9D14EE4F72FD7BBF18B1A724FF5A0958A063947C430\ +142AD2356E4400AAECA442E163372A8F1CD36E2DB988E7781165E5D4E7074ACE\ +40858E8370E883694AF09977704347FB735C8717C42BC4EEEB2AAA50DFE637C6\ +40909CE379BFB9E2608F88751377038D1669F248178AD580A908D7A1B8DCC7E5\ +3E01801F1E485B5893F103F03E0F53B2B1440BE95644D85AA7F6EB7EDFBB4665\ +2196695EA23C08573397B111FF909025E20C5201293B4D223BF7AA01DE7CB28B\ +94714370434B9588097E2401B62C7A0DEF1FBF89809E810749FD3CE9EC3C07CE\ +4BF4C43DC966429B2BEB4D711FC6C448A12097B36F1E6817EAF4937A983F85D9\ +CF3E62CC1B2AC6AE1EC9EAA8CD8EE2C3322239CFE5DB3D4E8786282E630A7D25\ +9C2FEFECA03031C960A66A71E436A3ED6F2F3CFAB4BD77C660D14205ABF606FE\ +561A346F7D849B69475AC9F6822D80B9A2E56D5D495E4B309B0EA963C9FC5C7E\ +F94B217EE5337989AFBC7107D233A8B362AC27C4F69DF9E191CD65AE97D6EB9E\ +5484EB6F10349575E4CAE51452380151F902415AC9CF42C824EB23C9541D2DA1\ +C26DB85F53CDAFB06A12B8393CD580A8E494EDB6710C720DCAE30832967E33E6\ +303A92B1DF0841D7724284FFD2E00B95C6D623B168D21AC1BD3C675EDA33182A\ +2C22370998DE1E5EB905372CC6EF32D5B765F5C94870DF4842D011603BE4CDB1\ +C227E41EB2F2E8542CD325884FEDC9C5C7BB07A92D20D64B836215C59F162A3D\ +A8BB67D6FC13FEF97CAB6ECB8A29E431A6519A6261C4521CCB90E6E609869E6F\ +E398404AE047F64EC4263566DEFEE66329DD40AC985EB8A08D26529A544891B6\ +F57CC235C63C09057AB6B6ED720EF41A3C9AE65768B43F6DCF4962A103DD93C2\ +13171DC2C9194E43265C689B49331450281A3FEBC618D1AA4D65A135137051FD\ +46B568CE294C89:\ +DE11315ECF713973B7D6E548DA33F68B53D8E9BC11F7E89C3CDD334EF748A58F\ +84B03B296F1B05357A8873449CDC49CEC6C893A629439B48B6DB517F4B0C9773 + +F5080D4C59E804BF8F34B334CABBCC7D32011BDE3677F4B9069416AC204114CD\ +9DA7A0ED0F4B4D8344416336EEC15553EF526B6DEC267B1242657DD0B508AF81\ +FECF9CFF9C82A6A7A9539814DD7E097615EF15373836B5D2F765CC8D5F82E904\ +49F13AA741D5EE2FE63898E55ACD85116846807606FE1E2E29F98F9940B067D0\ +D1DF01F080211B2EE4B0A30803782A7BC2EAFDC5EBDBA91EB05F7D7DC8E34BF6\ +D44FEC05824F53418F235FB64E899EE147BCB403C8855E94AF378D182D79C3EA\ +F977CB4E9D4A16D990A6C388CEB567B97785E6F2BC6745102B99AE765E960B6B\ +32BAF01E2379CD6ECB74D3E1A56552F5976DFE5C742BC92BE596CA742FFC3D0F\ +A032AC29F9F7C1A5C43BCCA62DF7D9DE35D0C7C179DB2E1AA255CEDCCA55064C\ +2049FEE1AF2CE5EF696ED4BC46B7C55BDD51F2D44C8713FB2475C0B85246AC01\ +03CC3863B7EB026AE076A600313F6FB40A4DF62A2AF81B7E917951EA870ECB31\ +B3401928B5046D9A1E62D14B30FDEBAF262868517318FE17EC3C0D52524F4412\ +0ED8ED3BA70C643300CD0BC70DA72C964A88F52C3A91EC20BFEB5CAEFCD4D9C7\ +685D8407476B5F34676C5EBD1E88A6CFF1C625322F8CD59B9ED60CEFB21F9491\ +B95E72791F7AC7EAA3C16159FE9DF7A989ADD6C2282C47585E11397EDA9F47DF\ +2B40166E03BCDD6186B46C6835118268DDBEF19A28BBADE1BDE0228FFD7E8B3C\ +3C598D89E24B8CDEE79C940254DE26CC6814BA2722E42F7571600B7325E1FF30\ +0251D52A895B8CCBD049B2953B8D231445F68F7C26EC25A4B8695C8AC116F736\ +BE939EDD762C9B4743E463C9B9B2F88E0BC0CE78781CDDC3BCA825ACD463C7CA\ +C2AA6C430BBE820EA94AF9A40B1B5C006E9641A2FFA6E427379E1AD49C81B983\ +20B3431FF0030DC683D61026438BC6A6D34B2C73704D9F62EAEB13ABB3E4B056\ +2B4E0482CD6B2D7AEBC0367EA29A88F4A76F3D76FA1197E1DCA92C8216C84C1A\ +F9B8C78C9E3A7799A4A79A783033B0F5547E8E75E69CF3615AB04EF989FE1A46\ +3B1672C571D50AB56972896E8A50C242F22C7F6E27CA4CA793F627E79608680F\ +5421B28BDD2589F05E65430DF774EE873FCD1234064F7A33CF5A1FA4E368137F\ +F9C1597F1FA0FA36493F20538077669EADFD3B06F788C912C715FB5D334DB6BE\ +D133A8FDC40F5496E66AD63881F0BA3727416715865253DC5290327B515BF68D\ +A188DD5B4B0EAC7CA712CAFA8FCAE0C5503FE58A219182F1C30DA6D0C19CFEE8\ +97B7D837C97996A35F4CA8CF0537A01D17E7DE0CC9C129E4DA0ADAF1FDA85030\ +DF9127BE628263B0624F372C47C3AC87EB945A57F5C732BEEE81A74030017989\ +92F3DC944114FF3D54C4666AC5AC8C98D0D5596CBDEB420665F5EDAAE747D54C\ +F7EDD37B162E372249D135938CF17D174D12D88279CB4C32BD6F018C766DA698\ +3D4EA51D6BD8FF0A9B34E9A93BBDA70CF1B4B867D60A74811FD98D52FAA559B5\ +2C755CB70A76C94BD19654CAE7017CCD70222BF08C5D7AD1F5E4E6344FDB3ABE\ +703452C29A696F39F9826ED8BC510A4A148E5BF8A5DBE6B82D7220164F08011C\ +05AC5159D52CE9D45D758B645BBB248C2D341DBEFA1F8602C5D458A64F38F3B0\ +4DB39089807B6A10E1BB52770B92CE72E2D3BB0C2241CDED35054B84558D1CC0\ +99EF7B2296951951D5B6A22F93BF962AC5EF8FB55EC6CC2B316428EDF12078ED\ +1B66D525D022819CBD489E1BEDB02FFBD507D55F9B5D4E22F6396EA233453754\ +688D20151A09C70044B8A5A9AC033C3C3B847AD833D5C05B33407666EE82F958\ +1DF9034EE15A9CA67D52F1D9B634B84C1B8BA9E515F1F060A5AC5CBAE2DE75F9\ +4E112F7198E239DF08D3103F065627438995026DF511C6E5BFDEEE5667D511D4\ +181850C7C5D179107C1B86D24D5532A88A4149A2810DCAE73731B0E1247281A6\ +FD31613DF6891B4C17B7A6A9AD9B77468254B93F85958AA0F01CEFC10B25169D\ +C46E035D3F24557B4BF0E7D60174219108D916FFDC55E25BFFD9809EFD058E12\ +C14F39C69D8FB73D3EC6458F47F2F8DB901BA76C86550B11B54D0641D4DB3EB0\ +00057DD00F2E511FB7A47E959A4402A3AC5462234B40B184020FCF7A0396C4D0\ +0A987C8741A4537BC17102A5C42AFEAB9F71EA66ED4CBC7B5EE682FF04F56F4B\ +A1EA0BB326C4089930F9E3F3FFA3E06637CCE32113881A06CC3A13837448145C\ +2BD01307A580FDBC385D8F46FB92FFEDBC8918D269DD1871164D4B3E2023441E\ +C8B99C82A5F09821CDDF6B38C9ACC3BF3A38D5628016159588C33EAA29D9463A\ +537C000A16AD8C177DC4CF716E625F46FC4CA8C19FBD8EF320F1D680639195C8\ +B195B0A02738E0665F4190D6287E589CD6DD45B9E8CC23B08E1681BFC6F66B88\ +DE6B091E825EA4BBFBD697E10BC407570AE4F2A3EBE569554639C2B8E051656C\ +C30C837F5A92260EAD1D552B45801B6D28134166796C87F900225CFDC3CC49D7\ +2DFBC18D8D95B1E160ED3CAFD5C3467D48AFF87402CBCB1E1420E3FCB588AA19\ +C8F42753B59DB6FB6A9FDBA127CA806DBA7DD97F2488FC2E438EEF57A4CC85B8\ +8DCFDE76AE1FF61225A1CA8BF4A14F729950322EA681B16D6492902506702DC8\ +F348E4D3AE7FB55FAC1231FDE82091B34F1791B6AE37587B10325F6FF5E23B85\ +5845B86EAE90785B9D10D90A16644D01BB626F343B908A9591F4069B21822CA4\ +ECF985C1E710475F33DF9AF4764CFB0FFE649063775338F15BEA7CFF29F16467\ +8160960A80ED148C9B7FAA58E9139911D3DD9536F69646F718F083DC9029D629\ +4FC4C607688AA75AF350AC2C0B001A157D023D73D86ED8133809FCB9592D1208\ +9CBD7A1BB6BBA882FE227C09A53FF088907CB4BC2FB4B7F62D41D3D397C4FE0A\ +D12BB3964370E21712951C679814D506E738C0201E42181D231136A435AE0397\ +B61CCBC5E8BBEBF8EA77C8BC48BD6211F29248F9D498D818E2B544D28A5E60BA\ +727F32EF4BA2707962230C900076FB764D0ED5CE078C9DB14DE894BBB836C6DE\ +9E83202AE89F9A8D8CB0341E1C81B5FA8B16731B8E231E969C0F1EF95336D4E7\ +3EAD6DA23DE3AD1EB608ACCE4D4D93996DD76EC1F5F2C576F6B3B76E07BD8A81\ +0FF5D88B00FFE48C42700B61CC499336E7FB57AD72FF44FC631C7222C9A3D1AB\ +F6E77B5ED7FE2F7228FED6C849BF7142C4103989A80F7C15642AE61650CDCA7E\ +854EB25E9E72F4C3E3768E6CCC8BFD556B56D3507EDDE9E5C331DDEA75568B07\ +813D20E8F4C9547838ED28448F2E67158ACF0C00B131473847816C5E2DC215:\ +740168046E1DE04598A62F5B92372B5198F2C44F579094D274EB5171CB4CD777\ +0763D54CB75D070184921C3CF65FA371E96F8FEC8138E7E1E1590CB0CA26007A + +08944CB473B828B118A31986DB67FC757F238182E790553404B792AA4F0095A6\ +A83291E287CDD16521A3AE8C48F56FBC909DFCCFAA7BCC570C2159F26592DCD6\ +B15BC4DD55CC05595AC634B2C3DE15360B0F07A03B5957BC9333CC5097919399\ +DD9973ACE15E55940178C4C96BB5E0A0A10BAE175769548EBCE11E0D7D9DB296\ +47F197D4B87F7039F5D4E59E016531DBEBF55A797AC9A6835032CDF34240A7EE\ +7423E89C09124829CAFC5F89431C8AFC54FD979E50D48A82B47A53523C84B600\ +4DAA323EFB708203E5388A6A5110C6CE2E341048A65FDEADEB3837A03420F9FA\ +DDC3F02A544F1E46D96B07C90C7971A7040A179E8198E90AA019268E00367120\ +D5F3D98A5CCE82C885E77144B1AAD66EE682847776B04F01F501DCBEFE390308\ +0A8058B3B8F1D823D917ECF31FC2D5B0795BF95A55C7093ECA7C801DD0BD0DBD\ +BEDE7D56513128B29FC0B4D25A6240B24C99E017BDFF7ACAFC8F8DE9FAF5A294\ +4384AECE82BEA04DCCC6D51FC6E6F27AA38F131B7959B13681A09B311D242E62\ +22A1CE5687DE5C080508B1DB16B6F8290D33A3CC0D0138AC61FD9093825E9D37\ +52889E9F20DB9F80F92750EAC88B38AC81C0016D40371EAB4A87E845E91446B0\ +A07081B84F559CDB95340CB020AF22AEA1BFF2FDA12F7A42973FF163A1C6F33D\ +B8B8214AE27ABDF1C54F5B03E29310FA210125E1296E8AF93A2996DBAEFBADD4\ +C51C2C3B8A3E2BC9FE060C42BA32768F6992A99599206CD2291CCC5BBD50856F\ +7F8D2D0AE1EFB5892C15A799B77482DE4553736B162ABB06631F1688F6746E7D\ +7A37EE7EF24E6CC901175F04960C01990178F81E957E941DEAAC8846B3704E24\ +204F43DDB0765C433F3F7D4D201459CD65682B7DDF3D47E95CDB31B96A4CB229\ +07F08BA6E92A4A07703B2DCF150F922C4B7CF181380303FB72547847305999C3\ +C8F9AC877D05D9DC4159DEB8A13D36AD1D533A56950E20F906D29D51DDC45BD1\ +5C1773991707480E37B827044BDC6473181B760A9036E0D3FA491C2F08C55130\ +D8CDD5AC8E97D0813164AF3D28A585F0C2EC7004D498F95C6B62231A632A56C2\ +D0C48FC3A6992D4051957B9ED6D9A86DBCCD962A8883CF82CAF01DA2F51A203D\ +56B6089BC8FD0B1BD414C8063031ED469555E22EF872689C130B1C101034D572\ +FD8CD0EDDABEC9EF1503D7F728B0941EFE2B9512438C7DDB176BE2EC2D9FFCD5\ +6495A4511428DF02819CDDA18D1ED5D3B16C6F42AA0AC681A9FAB51E8A1A856C\ +15C51A3EC1031427142EA12543014DD4ACAC640B8A7729E63AB7DF1051112CDE\ +FD4B988A2258334FA9A7F5B3A87A02074B9F69DD81B83FC74089A91D76AA4041\ +259E80FA255F2084902AEB9E996AC2288AB464BDEC47AAB26A28A2A819498975\ +5D48FC9A5C9279285F2F1DBB8B8018F3E4E13115D78A879792E45A8F4F24ED4A\ +317440BA63E6929056EFC1D2529B75A709D6C0097DC2D97F646F334EBE6195EC\ +5630132FDE58E25DBC17DAD822D9FA0938A2A2C926B105D108403DC29CF371C3\ +504FF73BCE9C7ACF9A74C4954CE6A32DA96B21CF3211B3E49953DAB78C49C3E5\ +32A349003C59C62F7D40261CBA63A9EA21C89A38AA63CE431C43AE261C4D9999\ +B1CAF491FAB8E7BE6E8C3454F1BE8793B2D27141FC107DA599A4694C41353D77\ +85C05B5E31440458D17C6DB66FEB8A9C5C073FB946A67AC0312BB669D9B12FAB\ +AA5272CA6631379EF4ED420A4424A5CD08526384C047C33A84D5D7DC0C215366\ +3B54C73DD799A3568C01B818992CDF8143F1DADD6B50CAE6EAE13AC66F31FFA2\ +B362CC4D2880592B7FEE4B9E4CD6AA5E5DE27AAB9B5DAD9F7D39407AE927530C\ +AB2B61CD7394A21EF47BFB813B5EA6091458D239664923280ED0D5CCA8285BB2\ +281A2F9FB3FFECC8E9147E1E8FAC957D90C9E5F513738745A47C2AD0C31FD898\ +6EF3B6388C6E821F166513811D547AB4336B5E04643497FC9F8D6E380EF6478B\ +82B6E2F5F65DD98A63C68C32B94610E1D3B9538F13A7688FBB1EC3448BE9BD77\ +BB93A34546172AE8D614F85228988E7FEB18C9A0C9827699E8B3CBC69750BDFE\ +CDA8268F694F4C509BEFC1A1166F85C829725299D173F867A300987A2D36D1BB\ +BE37BE3208FB8EFE9152A41A5F0E931B6382FF7F9B18937958FB180E61F2A8C2\ +8F36C3C80C3722935AACB81C24AA17FB3E7A1026F7031A7449818ED62BA7705C\ +A27C2D3268F90B6322921683DFF800A306CFC186CF2A61B37F35837B217E3B2C\ +ECB0843D84EAC67431E3D689F01522D4A4C73618B7C2965C9DABB15C0BE637D1\ +0CEEF72271CF39A7B803B41767BC34433C3E6FF449A439AE13DA1EAFA038CB9F\ +2E1C84F1CE39C05DF56FE3D7B82386C4E628B6E27CBC5D575C66ADA3510C246B\ +D04DB48F4AFC2D7352966DA2266C2BC9831532F53655D8BE42B421AC0D70D8AD\ +1D3587257886DBF93668E907E861BA64F45999BADB0F766EADCE5238B5ED397F\ +265935194812C03C5769137BAC97140525303CF48D65F39004A3F59B1FAB0989\ +5CEE05335D15B9B12265892F4ABB92AB1DD2002ED00CF3562CB67DFE1055968E\ +4AB3306BB34BB87D0F64B26848812A2F7B50424A21FF94081A7F70F7B684AB0F\ +092B2B085DCF84CA38414CF7290F607BF79C37EA84253ABCA8D4184D2DBE2E90\ +0200B81479E1CE8B71DCF2BD6E3C557A8E431D627BA669C2EA03068E0F7EA62C\ +29777B22142D7A1D451BD541EF8EBDDBBA4E3BD8FFCD340E935BE7C66EFC14A1\ +3EA48134F655B0DE3180101F09D204C379743A357E6DF1268B55A9F7524398EC\ +F3A59849A27B142239059998083E8FA91785E91C4D220B2FB17E3389EBAA384A\ +49D89B5D78136DD2454F06CDE9837F096B744D53221127869904AC227CDF30BF\ +EA78CC5545583F999B9C42A1184E2FB9FF3EC095B9DA0D138205C4EAC4C8C480\ +C43153608849F63E161135C79D8B6C9CFE9B8DFD8AFAB559D8B595DDD4383503\ +3B4BBD391E028BB2A60832D9B697EE61408F149744DCE71AA11BB2B0436C1E26\ +26AC3A27CDA293366B90B9CDE2D927855130758D3946B867192DCF3FCE9A3B9A\ +5276E8C37B8CB136FC90A6DC22650F95E796A9886EFD3F424BE63A66DBB1041C\ +B3D4A06F4E7EEE89F0B6D15C36F9EA010C66B332011C8888E8E4AB2B3AB52231\ +91E1388613A0FD0F07C1B26D7CC7CDF1AC62A226454D6291B431CC3EF2DB2B24\ +42B37DEFB942117FA247096BEAE598611B8104F37BEBEDD8BB8B949A89B5BF8E\ +228ECA1D8F16BFEC75A02FFBB4EEE3A6D4A6087C43634D675311E72A9F3253BB\ +5DD364E07EB4B9C84F586BA267BAFFAEFEC79E03B83B18595FE06D7E063EE604\ +FF287004D141C1A43AF0CA7C5651D98F633FA875B4743353FB07BDE59B6567AE\ +25F7095F1D9EDF30570E2F7D7EC194216898D910F9E295A41DFEE072CB56F914\ +BB78CC9854129250F9874B63BB3EBE9A1CDC6EBCB0916E1C440354DED6AA818F\ +2811DA913912A21D3961AC94A39F0827D3A419616905DC45842C8E69A43004B8\ +AE922C8DE1E8CD0668674A7760153213835BC63FAE4F8D65614AFD74A34D42AB\ +AD5025B884B34639340B45D49CCED423771916E18AA077291923017CA50795F3\ +B7A3F349A3D29923833CE57801C631576E23B838A7767CA1BDA92B82AC502DB3\ +688FFC83C09A4E40CAC31D20D9D32FA6724A80BE7091CDE9C7A6560CFB326B46\ +7CADDB9E9B7A491EDA283EFB0B61B4A1116DD859D5C0897EAA2A3FB2CD82FFB3\ +3770BF9E08091363B6B81D23E61C2A647D2BE440C5C79EA89690656D9F10B1F0\ +7942834E1CB6E2D2DF106EB6D6A21FA23819E65028515E88BD279F9317BEAFFD\ +394EA51F8639371C3A89F11305A4CA35FB0711F5E2C7C3DD1659C79024581211\ +3204B4ED8AAE9FF09D43C6DDB13F5070D98831B2C7639FB6B9B01C288812DDFA\ +8861DB32DC8268C07D30CF969953042B3DAD530D9D744C06AABE7A886C0FE57B\ +09B7F42D193FB3E9C06329818251A2F7E6474462C95DED:\ +9EF7A93FB957D1B7EF09E156186699159E65461C9C5F478CA8F1B25C6C6AF982\ +AC15F65E57ACD3ACACA75CC15C38616E0016685417E37DED05B4FE579EE2955D + +1A3DEAFCE70AF6F3F55D66AD9CE78D5F4D5C5F2638A810AFCD07D67E9F9A1380\ +D6B34BE482EF030C22F1E978F544609CCE35A74C5109EE7038495B6210CDBCA8\ +DC82C6E9E7B0D593FAD9665382B3C401AB8941DF71307DD77EBAF140AA66A1F7\ +6316478850E58886A9610631E9C722F459FA00C0B53124FB4F12778BBBA37608\ +26D3DBA67CD030A96B654AF93F8E395F5F439549489F8161683F124BC980E693\ +9C83A6085E4B6CAAF8BCD89A0E01ED70DB487166CC29735D9235A9CDC57B80C9\ +C2E591DF6322F5BEDD32937073F781A30389552AE83FBE147D1B3D3461A3DF96\ +C15CD96900C56718EAAE838417057579115936862679F5F2A45DADF65D14108A\ +F1641DF987B57986384FA1433789F5DFBE87E90BD4E9D8D4D0741FCDA7348322\ +B967B566B18612DBB8FE64F151947C3F7E361EE868676BCCD0CB3A1AFE046BE7\ +0057A05ADD3E65AF31E3FF414A627C0183E8FF583B41B75B203650420216E6DF\ +CAB289665F054CFE3EA0943647528518573BBB1D0F27E1449E98739EAF0D0094\ +32DF0C1EDC1625264B94A71DB762659FF5A3A7A867F182D1F1FD34B341A4A181\ +221870DC4A494013091A7E3B2B07E0160C438F1EE1E8A2B989C4FFEC36B5083E\ +A427606767C29672F44779A8505B422B25A56907F565B27690D011426A62DF00\ +36D57D967CD1D14E915BBC2691E7AF818C769D9E1F9EDD40894BE88FA1D7A595\ +2AFD898E837716ACD73953BF2D1D448123FD1A0276D2C2EBDC760A4B787416CF\ +AE5E963FCBDC8B551CB70F91DA0ED4A8090FEF178E879F2C34F3A269DFFFF097\ +72D44A13D7A17468B5834C460957D5243C325F63F05F89D4ED98D361E7F0AB8A\ +83948A64D0CFF8514841AA21C7F337920A9983E59BE4A0F1339E1E462F92DC1F\ +C070126206012458A499A8111FAE078E00B0CA3BC1D6C7087CD318D5603C1C7E\ +0425E6F729CEECA5F35B82F8A42E0E9B950EFB0904C5FB5C06D91D239913665E\ +D1F1EE4B82185A01BA86CA2D3EA94E5A8842231A94C05280183B7ACA28998410\ +3F122203EC2FBA4A382E6F5236D6F68DA05E3BB0C558421F0EFAB91DCEEF6D1E\ +CDC60F9B88F8BEFE31CDC3C2F024A1AF2C7336AA5D151E8CDA814A5FE898BADE\ +B9DD680E337E682EBC22BFAE445417E37D2D89A338659A280AB1206DB74DD42C\ +6F25639C1803BFDF2156DF613B0F5924D209F7F9003CE8794F989F4F27B82121\ +210F4F65EC5A1F7723305CEE438C41F793EE04496BBE337BBD2FD3023830B1C8\ +889C6F4D0C1192E364EDBE1CD987BA5D66224EE9C9405E1DFCEC0EEFFC5C73D3\ +123F6731C6295D1E6B854B884FD22B6A3BBBE5395312585CD138BCA67532C6AB\ +71BEBC6657C50DA87D2AC6068FA3970202C5E15EB7B4B3D2676C0134BCF1EAC2\ +B26BA46930B5E660B16060894884C88BFACD6779276B86F685AB6F17C6D53F62\ +1275FAD66D021D26D1D480AFAB4B5EC75E0E763FFC45F599EA02504DA5D91EB5\ +EFC3E4AE196F219E45E7CB05594958C876FF474A020EF73C1F09B1F7F7457E81\ +6D3AF51D86663D4D461754CD5E907456691E02446D6CACFD33516206A3187054\ +3D574592087773653D4086C2BDCBAB3C9B65CA11AD0D4E58DDDA8B4403099898\ +57103929549B7300CED42651D4086661694092C42875CB62858E6D1BE5F7274B\ +4BCD83AA4DA05CACA186A30902830790F9FFA24418E1F9DB00FA40477E83B05C\ +2D11AD7D81DDDB1E31F94A9DD5E9E13391C22479B570976E3AFC1BE41086D3BE\ +6689D87CA4326A7CDE8E5B396A678D3CDB2C80FECFBA2BC799AE8B1528E96D88\ +0CD098DDE910D097EAAE660AD4D7EA51C18F18AA1B39614299A172512521DFD2\ +31B9840909839EB69C892EE23F1BCEEC1FADBA75786C7DED93BC9983F74CEAB3\ +97EB8BA84F7E4130B34258D628594A6F9E2348FD91BA2594E07B8057E8A2AE3A\ +DFEA0EF919555385977041C5B6DC4F3880569171F7217AAA9A85F2F5BBDFE3FF\ +DF79248F2A35FD4DEC34980C67290339B1C0A5A6AB8838157AE2F5140B4A2492\ +4A6688AE5CE72A48103EE9029CE8A0F15B1FBB19A12FAAB80A7CD9C0E389FC27\ +75833E3190F1CF735ECDFE7F6B6C326506AA82613CBEDA8DD3691B81F4C1E3B0\ +FC32D7E6719CBFC12F4A26E0FC29D6417953ABC9568DB4ED9A294B9FD5F2A666\ +DDA546ABA301B1C60985033953EFD6F4538333B5C7DD3148814A3FD7927C366F\ +40B3D7ABBDEB2332DDB586AF80959097663CFAB2FEECAD6D368AE10EFF9663D5\ +F8BAB95935D25F45776F7F04B46817D05165A9DD4770509ABB92F8B9E7373CA7\ +80703569981754A51D6D376D65C57F55CD70E2DF5FDF5A6B829AE30CE3BF9428\ +15C8B4BE858DB58151D02A68AAB9FD373E047EFA51BD1A0CD1B61744D9E97CEB\ +A3334B3BAAFEA3BC9E43AE097CF2C3D713EECC247FF43EC74D54907D8BF45E45\ +B2E0E11D82B126A8179D3F66C055E11F69EA67AACC5FEE8AF01FAA379E51998F\ +5070F9EE0FD30A2EB22A925586FB1B39024EB5EB1E127C76A149E7F02AF1B73C\ +16E9E5A5DBE378E08A9FADF1194C625132AB3FDEFE8FE9A89BB8E0035A1A3AC5\ +278F5D3D0ADE0E41C81C6853A41C4AC45BE3F68180FE23F27F18BE2E339DE1D5\ +59D75DE63ADF7A32BAE42B037AEAA3E123A5314891BCD35CA48D57DF4C17540E\ +97202A8EA1328DA25B1FD6BE2B56AEC1E5DEB209F3B7A13ADB1CBE53EB645956\ +E577A7621D74E42376D70BC5C4AACD239A852FBB7B3F62CF59FE10438C1DC8E1\ +E46566325DA0CA43AAA63FB7E0B450A2DB3E3A2204704D894DB24B72B3078106\ +E096CD543DCF027650CB4965E38AC36A8AD588C5962B4E26548AB88F0BC20E10\ +ACC1C3FC00EF415B3C32499264552B14E2C0E789A3B8A8BFF9620FD939D0B34E\ +806177EC696A4B3B1CA4B32BA979B2690CFB3A6B17BCEE6877FFCE757E4116DA\ +01099FFE82ADD5A0C593E73449A96DB9CC2B9E846D166B095174F2CAF8B35DD8\ +78C836D9BB6EEEAF8E1BC5D0E149C739828CC480D731DC16B35B80D4AD82ED7D\ +29BD05018239EFECF8DEAE180C6A459DBCBFE4AAB9A5E2C1E1BC31418CF2EEEB\ +31FDF8BA02C9A91525E9163F672BAE2EDEC38C1BDB84EA237B4EF86BF5C0F0FF\ +E178E3761E82D94F66E5EA40BA8170BF768409E1B4177AAFD9937BCE3FBFF590\ +320D7C445372463FBBFB34F57447F42C16E026F179CBF82F617C86D1E8D42F6C\ +908F9C6B77E38D25D51303DBD781FFAB569B4CF31FD0B947C45E1768A2E9DFE8\ +369F520DC38D77937B69B821DB4FFEA8F50EBC404F0587B5598189F54B5A5B98\ +966FD16801C87DE2C3C7813DD70DC600824D426D88C55E89D47214D59206A7A6\ +5A65DA7CA2E42FA62ED17E7AA5B3ED446BCC71F17FEC8593BE96D2037BD07F94\ +76D4D732B32BC5DF8C921316B45699004716FC89F8D45BAE402C26DBCDF1A340\ +847B932FF882DBEAFBEDD252E126C89A1E1FDD8908A1F67D15D8E432DAD8E08E\ +950A3BC46B96CB89CC5BDAC703B3FA3E986EF1C6E7E6606E6845BA1EB2FBDCFE\ +E744B5E45206F4A419E1CB103C8490EB293EE9AEC1F0A0D294F9D3847737413D\ +30873F3C94740E8FD072817815EBBCE3F09EDEC9D1211A9E99547D620B2EC56C\ +89E9CB8144AE9E46636324BD13C6CCA3AB9CD9FD8F7F937ABABC598232384427\ +A2D4CE0CBF9765F7225E208C3CE128602B0AD08A1BAAB77EDB3111F0C6CA7BA0\ +EAC9D89D5B4378EB82C17F6EA08308A79A53D150D3F85EFAB77294F02EE0E288\ +5EE2AB2793392B87DB11FA77992F5B4FD75EF2F1A822E87407A4878894215AB8\ +9B6CC4A120F5A78B3C31AB80FFCC9ACEF53FC6F7F85685EB9D56D30D87C21ABB\ +F1652EEF8F32C7C567BD1F08623B09C29F33561D42727A5649A3850071AA6C11\ +735AE63C4FD31559CE560B27A362786A83353FE460B37074664A9421D3B2F6A8\ +64D5ACA087187B27E2B82F31CB3DF5E985CEA271C609B94B4E58356D40C7D5C7\ +FF2E5990FB39588154843EA5FCA92F120075D4C4D006661A0FA1B0585454BEA7\ +25473EEF7D58117D5840C8348999003736C5EEB7858FFD273A1C3EB2812F5697\ +C59110275B08F6BEFBE84C92497D5F73B7B6F794A849713B23AC5F29D5C7112F\ +B2E7A6E89EB54DDFA3122E6C79624C1BF25EBFB9FE5CE6DAA779F3ECB2984DA4\ +2F8C6ADC77B21DD291E684FCA50E46070962A2D4F00813D8DE1B8ED33FED9715\ +180C7EA8E2BB74FA65D9C7F6E142F3C81CDC59172E1020F62F65CA5A12CF2BED\ +9DEA04A4D8CABC2948F7BE823A3E792625275B3925A6C8D8E2B428C75A5DB0F7\ +120278CD7D6CAB768755C7FE2FBF89FDED1FB38AC7F76A2F8798CA36ED42CB7C\ +07F006271205F546A4812C20077F050D4CDC79459FA686E97F0704B7A9FF7DE1\ +6318E862C53D361BC635A55A264BE15016545DBFCE3C6D6849576ADEFB6884ED\ +D768214E0B438B0231B4F2692C2C0B5C177674F8A0DE236EACD9E0CEC7C8647E\ +4E9A5861B957EC834A2F8572F01304C3FD6A06019E5F1499B62BAA8670B65246\ +7FA9A4F10F053263BFE9743CC7D933F86136AAE3A6FB56754D7D238397A0030C\ +EBEA87CB255AF36138C373DBBAC41DD4A697032E4796C552AD9C9B3FA713C3A4\ +E09E0EC5581E94BE7F31065157662F9E9C678B1EF1B8B8A847C51789C22B1841\ +BCFC855820AF3258AF9E08231090B45D10046A00178E89BD515616B8A44E77BF\ +57795DABAF40687B2CDA7A5014168F:\ +A2C211D36CF26297E82789FDC7E1564AB1A615FC6277E2AE77E1FE7370C0FEF4\ +FB7B360424C44F393FC4EC2AD5061E633AFBC8D3FBB961322CDFB7AD5A4A443C + +1633256AB03B20CE079196B708A1C02D1B6072219070712C8589EE21341D5075\ +2ACB6CFDA17E982D828BBD6CDF54BC7232FD418A323D64939928597B9B52F07C\ +F488250C5E42BFD3AB48012D709F8D747225839296386FCE5FC5AECC4BA7A107\ +6D089DEA8ECEFAA0CF66FCA8602395719C12A04F929321784D7AB8239FCE2FF3\ +BDAE046A266132B5C2AD9F7261F3014E87B389A6695978693D9371D0B1FF9C40\ +5F338C2FDE4687359603950A54CF4B9CDD9B24480B239ACC5405C14C886BBB03\ +78391CEF0662A38882BDD09E3866AB9A66CFBD28EB5EE4F8009BDEFC4AEB1670\ +0EBA7DC557B489190A71FDA75E85F7EF841697F70FFD4FEA185E7A67C81C5B8F\ +273BFB97B2CEF695C1C74446C4B425BE6B2E66DC0AAACB247E4467B7C7D84EC3\ +3B6B5AB8FA1979F503008BDCFF948CDBF1226B1B066CBCF34797298F3BA8C60F\ +A01E0AC8B803223C656112FB91435D75453BAE4707B63330467DD13E0A4B992E\ +6F7E46995899A2D95D23F4AC3D0802B2A6E7D024DEA19CA408C4BBE053F14C9C\ +E264F129724A18BCB18F385B1CA091A11434EA96D98C8D0602E98EDC8DFA1414\ +1AF93ED0BA66E885E9FA108591AE59E109AE34D6B9F5586E4B4D75E7DF7C3295\ +8A65E88A9BAF41082A0A3F11539DC4EA2CBD9E1C6C3C439B622F1DE574FA7547\ +0C8C939B51D2D1C2A7204B859881D43086BFD8FB90346218D099C5AB36846F3B\ +98A7C847318BDFA01E09717943FCD864C5A8A17B6CEB89D98E872D388F20ADC2\ +BE5E2006846904F41682FB1283214F3D20DBC9FC9E0FF571844A1282E88590D7\ +C085B2C568EC5ACC4462B389FEAA5757F7033187E2DE31955FCE55FEDC909255\ +048B327CCAB2E582BBC9D8054BF5CB45145C7D3A3AF9CD5CF6ECBA490C634ECF\ +00E646BF95E8642C43A4978EF08A574EF1F78F6CE57C3B34B5A123D123617FC8\ +EC9B2AC0F9B70A7F6062D38DD7B8E9FB4ECCEF13DED5C0477483ADDAE4F1CC0C\ +FCA274B1307ED0DE72FBCB819154CDA897D7575213042615F1741A8CB646A39F\ +8D134FDF9E60E000EB8220F65CC30F5FA52C431B9E3B6101B96E25B8D0440B96\ +E572A18A01747C02AFCD7513542F7AACE194632099D16274F31EBABB60DDD94F\ +E43DACCE900EC0902EB5E686D48ED8D09AE63DA0E15C736809903A0297A92DE8\ +4E0260F11F446E1FC448E0EBF59FAEA3C726F97925C57CBDF85B1F77078D3625\ +7C85D56CBBEDCE180FE12B687ADA2DC9912FAC60334166BD2CEF06B089ED5C95\ +63844D71D8FEAD2F3A93F3C07C52537336A8A70BF5B596B9007B9FDF2D082000\ +F20E6B70D2A7E6C7ED27C4146895A6D85A246F623C1B9258A2F891F823ADE4CE\ +FFD59D4FFAD077351E2F506E9A5BDD3900F0204B9E8969AFE72F5DCCB9CDF986\ +D197AE4C4DB53014041AE6221B750E5290E307AD292C8DE6B899235212EF8CE9\ +54785537DC9435AF11E0F3427A9C7B22EFA752EA0B7EADE5F6EB4093BACB7867\ +6E506698139E4F774423B8942166F9A7D22480D814FC0AE19CF4960FBF6E01FF\ +A65C8DA5BED4F1AE2B9ECEC5BE7B3C38DD4045B0C93EE6CC77A7E61E85D331B2\ +3C0D164B104518B3405497054445A353E9B48F2AC5E8E96298D6655614336CFF\ +E6D8C9C915E387391519AD2632366AA3BC935030FD12927EFCA17505ED74C946\ +50C778539004854DF6C24269AAB9C273A493D3E5B0B1D687C33C2FACE46B4BB3\ +742D6DF743D09164D2E0EE7F6BA128BD5FBA2E3B33C199AE80FA9DEE3AD811D0\ +2BAA3D42A6362B2AD47BBA8A2C5CD00B46CF22CFE367281488A4852EB8B7FACE\ +79F0CA6F8E78D32578DFEE01711C4DCF3C26D0BA13F3075478E708C5C5315AFD\ +C2E4C0062D16458213BEC506A9E991A61825FF78DA9BA1BAABBEFA56B4A8C9E2\ +E7B60EC4B7B541C8E0F79C86BB5F03F736761A37169B2AAB8884EC6EA217B02C\ +59035F5BB327243D126B78D4AAB430212439B5A75B80618DAFEB66AA3AFF866C\ +4DAEE47D374B512E74ADA933EF24A841BA271C6F02C870E8AB950FE06E93C91D\ +F0E99165DC01BCB190E411ECCD85358FD4A88127A22E4CF4266A90845124BF97\ +B25D7B1C46D3A0D68A684F84E2A638C692A52CB6E8C651A3AC492B0460004073\ +D5349E35552359CA37660F77B2770D6B2B3F7B1922424AC4A8598B4C61A6DB50\ +7608A72A6A7D573CC055206276E14005A28A0EC41F28D7E260611D40F089FFE5\ +E529375691412F4E9E12E62C3BE2C563C26D2444EA9C69E6C935FEB4DC4E802E\ +5FE3906F8ACEF4798D940C3CD574BB5E74506C3E0B70CB62454A25F589EADB6B\ +0709FE3B50417CD1D98F08E08B7CF68A04CCCF8D6588F9FC2F31E533CDA6159B\ +AA4297FA446450D71C16EA2324EC09773E7C8817ECF680ED12F64A04863EFE3D\ +9D8760F34DE5B0860B3991FF0EE5EDBA22C4D69120DE19D5429E4AAE91C9E7CF\ +05CC807159A58F13B480872AC1609D87E7009DEDB71C09CEAAB640A2B6135855\ +CEAE4AC2954933A0255B425D9FDCD9C246F82AEB7C3BB78C6E73E03DB7AEC424\ +5A28693FBD36EF4938D59CCE19EAFC00671A0851612406A075713C5D1154D8E1\ +3B59B7C5B0902239D4BACFA386AC817AC5EE02A181A9A47C622B3ECF287E1484\ +3D452AF347110498A620B34AB4E116308D976062C9EE9CD35DB6CB79805B93AC\ +9A15AFBCB52F1ED4309879D1924A4BA190B0B86E60A516E77D34B4E0A49D4EF2\ +CEF3CC2F410FD8EC901363FC9EBD75EB460D4D8910BDF27CE26A8B4AEB94F9F7\ +6242401DC35D0644842B99FB6C439B82D82ECFE1AF0D01F9BECB15BEC83F13B2\ +60F7F714AA381032923FDE8F8018F3518547451435C9A5207294D08A907C7369\ +6F6CB000745E072E25B73B3EE11595433D27A1F11468686F08094F1D31F5ADA8\ +1F11F0677A29D72EBB2E1C4792CCC607CB938647E1F153F9EEF03D982595C631\ +E49B6B7C1FA003A6EB8D59CB8892CD0888B05240F12701753F89007C859515A2\ +FEF944BC60B36003A26702AC6FE04D2E942978FC31A97EB29871D6752399D352\ +1720729007B6A7215A4282B2A4EFC2C56BD129E74C9B00847692B96FCC71CF7A\ +7F19F3FD6B45C519FD73B4860880A2DD74E5727B31A93F0A87F0078155344AE9\ +F7BDBF00D83393B634B5DCA88A398E42C320EB95C4A826ACEA90B65E4767B2EB\ +A748F97C247568393E2FD3A66075CC12935B6D7EB5C2FF5282185CB62C73972A\ +37B3CA508004B4F796BDF82B83B5BDF90D6BFD32B5089B0CA2683DC7FB2337DE\ +42E650ED911DBEE1EF98257F9BA5AF54B1A54B04C0087A5A64BA779D86461BA1\ +5337C2E7D4955FDD777A025DE226306A17C384F1C52CDB5946FB0B46DD5C13BD\ +7A55FE2E27E4C6D40D61D6FFC024468F8EDFC7C7992DF5DC5D05063FE7231992\ +24F53678E48F25250EA28BDF1089718EB8B730D1C06735C2F871164E2EB5E885\ +A8DFD2A083BE97EDC94159CE9BF75D2433F1D782762F771903CBF9A1C9D13F71\ +0BA0E151B079DC0A8262BCEB1DBCBBC0F35DF6EECF7BAA7105B9808745853C96\ +B4372E95E482035916B726DAC7BE95A72B19DAD48DB1B19E6EB2EDAB5AC1B301\ +3839E7806625ABC129F41813E6D71EE4AB2040D81E42E6ED73ABBA64FF2EB433\ +B910EA7D4F5ED3D8D27D39BB454EC019DF6114F544D7B155549D0C56D14551FA\ +F353994A80F30F3C97E863A4F2AF316468A568038EB4D799350A6FACAFF90ECD\ +44E0F44EFB6DC42EE4B0DC2C59EA9C1827326DF08C0A6E55CF4F9C3EA0E78CFF\ +3635F5D08E44F1400D20F638D56BA84B4832090454DE57EF04B6C8805A36F63E\ +5CCC6E830C87FFC164647CED20E4C486D09DE7A5F9E4B68D5456CDB22B0DDED2\ +B95B3BCAE529215C2D25D6823C7D66A4FAE0A1E9F022BA5663204F2314DFA51A\ +1F10E11D6D62A8BA6C28B6AE7DA1DEB5B57F2B65D7456059AD9F03DC5A524054\ +DA39DD100D74EB657DE219795E3C45A0E4C762BA22F9DA9D8159E425A1EE783B\ +4B22C250D8894CBEC706CE16D5CA393404FF478F141BE7CC69E45B077BA1955F\ +1F49EFBE4847C795347F703300F672334F490ABF8B644A34B56DA00EC45A3503\ +14B9ADF27CAF7C51CB7DBA0C5477E7D37662F4F23247BCB8F7DD5F3E9CB8BDA4\ +0FA97568832AF0ADC68F71422E412254A6BFC8943BB465B01FCC8DE0B957677C\ +78BC1F7566953E9D2446239F602C682A521C14F741FEA98C7E27AABEC339B6F5\ +B94C78287A894AFDAE971F8DA7C7E4A4C92C8DA47BE82DC2532EC2DA9BACEDD2\ +BE6DB2B2FB34DCCDCB34116507376578CBCA105E5E443BEC0F2EF23BE34CDF86\ +2EDAB34F0FF21335E3ACD92F59688B419F824EA61EEA82BC80E3463452192377\ +131BA51FB0795E089FC077D0ECA8012E58B0637AD7022206887FE9EC00EE5DF7\ +AD2E26FE819EE35C7A179C579098AA3DF645D9064CD557DA90BDD21F871CEB04\ +8CA56DF9653A10ED60F5E9F0ED7F8D89BCF5C22D1143CF44718FF2DFD8E10CEF\ +8AABB67D2305F18177C1426BD4CD03F2625E459CE905067826A214E08E56D8F9\ +455593E6B324E72DEDCC429D3BEFE2AE0599E360DF95E80D453A3A849E48389F\ +A745635BEDE30E7932DE6A3816E31A2217F98D5E40238963D0A36C159FD4EC32\ +D8A5CF59D433DEF3378634AF6887FDB3F3EDB96FC8840FE1B538C329674AE810\ +E8C8B2B46DB208716D38E9D1AEAB097068AD83ADD7DD2647839B3A7388B0615B\ +DE26F8692E9C07D8ADECC2A875203C3D3A9C6CB1D7D06307E9E1D9C3BC536DD8\ +EB271E9A2159C904E61E8C9357FE759F36366AEF5A3D14CEE82913CD2708AA60\ +69369CED763C8E830D70924E82E9015C2998E86EFC1DCE6AC2EBCB49455542A6\ +D7DAB265AD6D7381FFEEE1AA40F8FAC0659B6FB56BB03CD8CAFAACD48D13672F\ +7D524EB9684CFED4DBB7476E99149C28EC08F33BA6AFF839AA178F86B8EEAF17\ +39C829177BA78547AD394136AA3FAD451A11E9642506568B39668B2436610E06\ +EA45FA11D04D3759B033B5382645F15B3C39270B81B80487643913A24F2F1C1A\ +1ED57C85CCDDC8CD6D59B62FA67CC80572968C8FD01894F0153634C88792A7C4\ +A407A4A4CE46CEC5FE5D2569F95A27DE242444EA0C715B357518CAEA23E767E8\ +545983F0D3A4DF66111B4AA1D399CCAFD796D7A80E592D5A51D2B3F60B5B04F8\ +D9C009CA56CBD4DD84127A29B72ADB7645FB7279C9818B2B43963BD605F45B65\ +75A5E2E369E0B401F5EC10EC703F1179B0AB9D4A89D6F096573952E513827364\ +A84D38922734137E969D8167D6959B70F42F2BDA37E4C989ABAA8024C1A84ED6\ +BEB74780927F78B32EA736B9B2B4A795C355C0319811729D9CC399D235197303\ +38D62E16E5035FC52A817090703FE776D65EF9FEF5BA5F4FFEC3CC8E9EB2E312\ +C50A479BDD4E6AB0A56C18C2DF69ED408417BEE28BB41DD13F8366FF6EDA4B34\ +090FC9BC045271:\ +B5BA769BC397D0F2B541E1C996C40F64C3E6BE52950898BC0380513F8E6F754A\ +41025B104D2B5BD872D1D427A8E98F089C9AAF3B5071668C65437F0EF48855CD + # FORK-256 vectors generated by the implementation in Botan; there is only one # test vector, and it only covers the compression function, not the entire # hash. The implementation of FORK-256 used to generate these vectors did pass @@ -31768,7 +35832,6 @@ B8847AA6FE095FA629D090307AA2D686C7D628B12D63BCFD8E4F6BE8CCE039E8CB69\ 90AFA11E57550766745BD3401459373A418A360D4C4B9275714679517C73F60FAE:\ 81D2AC8F3A2C92E190ED1AAA0F7EEF24579E697A -:DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 616263:A9993E364706816ABA3E25717850C26C9CD0D89D 6162636462636465636465666465666765666768666768696768696A\ 68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071:\ @@ -42748,6 +46811,47 @@ C65D515D8FDF3465396DBEA4C44F6F069C597FF9AAA32227:\ 0123456789ABCDEF0123456789ABCDEF:98E523EADE38B3BF4EBF51D7EE814316C9EB3159:\ 0123456789ABCDEF0123456789ABCDEF01234567 +# From the NIST submission package +[HMAC(BMW-512)] +53616D706C65202331:\ +7017DB5D590A803ECDD0E87818083D657BB85636ED039BAAD3185D8CAB82E017\ +2D1957757D6E5E2F288D43E032635E8FC4B9FAA9FD445CB1161F7786D805529F:\ +000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F\ +202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F + +53616D706C65202332:\ +CEF9110B1F90A24080C8CE794FD922F8669A1A0A74299DB9789D9BD9CCC8BA7E\ +9438BD2383F14D3C9278FDB65C0A3FCFCBF2EB570C08588488F5F9AF428D8F67:\ +303132333435363738393A3B3C3D3E3F40414243 + +546865207375636365737366756C20766572696669636174696F6E206F662061\ +204D414320646F6573206E6F7420636F6D706C6574656C792067756172616E74\ +6565207468617420746865206163636F6D70616E79696E67206D657373616765\ +2069732061757468656E7469632E:\ +8519939233A4547258AFB322FAABDECFBE3F99B83CD0F760944B3F9B9FC0CD2D\ +BBA98A069CC267CA80B53D9BA6D9E89C5A02173C661E5E715902D5F5B23FEA9F:\ +505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F\ +707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F\ +909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF\ +B0B1B2B3505152535455565758595A5B5C5D5E5F606162636465666768696A6B\ +6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B\ +8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAAB\ +ACADAEAFB0B1B2B3 + +546865207375636365737366756C20766572696669636174696F6E206F662061\ +204D414320646F6573206E6F7420636F6D706C6574656C792067756172616E74\ +6565207468617420746865206163636F6D70616E79696E67206D657373616765\ +2069732061757468656E7469633A2074686572652069732061206368616E6365\ +2074686174206120736F757263652077697468206E6F206B6E6F776C65646765\ +206F6620746865206B65792063616E2070726573656E74206120707572706F72\ +746564204D41432E:\ +44FCDF6C712B75BE3CA93EB2F98ECEAB23D7C5A3839C2D267CFE0A9A202E7375\ +6B8B30882D94725A82D2C705B5256154231EC14756CCF4A7132E911CA24C1AAB:\ +505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F\ +707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F\ +909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAF\ +B0B1B2B3 + # From draft-ietf-tls-seedhas-00.txt [HMAC(HAS-160)] 4869205468657265:\ diff --git a/configure.py b/configure.py index 4d923d78e..88eb45963 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 = 2 + version_so_patch = 2 version_suffix = '-dev' version_string = '%d.%d.%d%s' % ( @@ -55,6 +55,12 @@ class BuildConfigurationInformation(object): self.checkobj_dir = os.path.join(self.build_dir, 'checks') self.libobj_dir = os.path.join(self.build_dir, 'lib') + self.python_dir = os.path.join(options.src_dir, 'wrap', 'python') + + self.use_boost_python = options.boost_python + + self.pyobject_dir = os.path.join(self.build_dir, 'python') + self.include_dir = os.path.join(self.build_dir, 'include') self.full_include_dir = os.path.join(self.include_dir, 'botan') @@ -71,6 +77,10 @@ class BuildConfigurationInformation(object): [os.path.join(checks_dir, file) for file in os.listdir(checks_dir) if file.endswith('.cpp')]) + self.python_sources = sorted( + [os.path.join(self.python_dir, file) for file in os.listdir(self.python_dir) + if file.endswith('.cpp')]) + def doc_files(self): docs = ['readme.txt'] @@ -87,6 +97,14 @@ class BuildConfigurationInformation(object): return 'botan-%d.%d.pc' % (self.version_major, self.version_minor) + def build_dirs(self): + dirs = [self.checkobj_dir, + self.libobj_dir, + self.full_include_dir] + if self.use_boost_python: + dirs.append(self.pyobject_dir) + return dirs + def username(self): return getpass.getuser() @@ -115,6 +133,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', @@ -137,6 +164,10 @@ def process_command_line(args): build_group.add_option('--disable-debug', dest='debug_build', action='store_false', help=SUPPRESS_HELP) + build_group.add_option('--use-boost-python', dest='boost_python', + default=False, action='store_true', + help='enable Boost.Python wrapper') + build_group.add_option('--with-tr1-implementation', metavar='WHICH', dest='with_tr1', default=None, help='enable TR1 (options: none, system, boost)') @@ -327,13 +358,21 @@ class ModuleInfo(object): lex_me_harder(infofile, self, ['add', 'requires', 'os', 'arch', 'cc', 'libs'], { 'realname': '<UNKNOWN>', - 'load_on': 'request', + 'load_on': 'auto', 'define': None, 'modset': None, 'uses_tr1': 'false', 'note': '', 'mp_bits': 0 }) + if self.add == []: + for (dirpath, dirnames, filenames) in os.walk(self.lives_in): + if dirpath == self.lives_in: + self.add = [filename for filename in filenames + if filename.endswith('.cpp') or + filename.endswith('.h') or + filename.endswith('.S')] + # Coerce to more useful types self.libs = force_to_dict(self.libs) @@ -404,7 +443,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 +458,12 @@ class ArchInfo(object): elif self.endian != None: macros.append('TARGET_CPU_IS_%s_ENDIAN' % (self.endian.upper())) - macros.append('TARGET_UNALIGNED_LOADSTOR_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_LOADSTOR_OK %d' % (unaligned_ok)) return macros @@ -429,6 +473,7 @@ class CompilerInfo(object): ['so_link_flags', 'mach_opt', 'mach_abi_linking'], { 'realname': '<UNKNOWN>', 'binary_name': None, + 'macro_name': None, 'compile_option': '-c ', 'output_to_option': '-o ', 'add_include_dir_option': '-I', @@ -469,6 +514,7 @@ class CompilerInfo(object): del self.mach_opt + def mach_abi_link_flags(self, osname, arch, submodel): abi_link = set() @@ -495,21 +541,32 @@ class CompilerInfo(object): return '' + def library_opt_flags(self, debug_build): + flags = self.lib_opt_flags + if debug_build and self.debug_flags != '': + flags += ' ' + self.debug_flags + if not debug_build and self.no_debug_flags != '': + flags += ' ' + self.no_debug_flags + return flags + def so_link_command_for(self, osname): if osname in self.so_link_flags: return self.so_link_flags[osname] return self.so_link_flags['default'] def defines(self, with_tr1): - if with_tr1: - if with_tr1 == 'boost': - return ['USE_BOOST_TR1'] - elif with_tr1 == 'system': + + def tr1_macro(): + if with_tr1: + if with_tr1 == 'boost': + return ['USE_BOOST_TR1'] + elif with_tr1 == 'system': + return ['USE_STD_TR1'] + elif self.compiler_has_tr1: return ['USE_STD_TR1'] - elif self.compiler_has_tr1: - return ['USE_STD_TR1'] + return [] - return [] + return ['BUILD_COMPILER_IS_' + self.macro_name] + tr1_macro() class OsInfo(object): def __init__(self, infofile): @@ -543,7 +600,15 @@ class OsInfo(object): ['TARGET_OS_HAS_' + feat.upper() for feat in self.target_features] +def fixup_proc_name(proc): + proc = proc.lower().replace(' ', '') + for junk in ['(tm)', '(r)']: + proc = proc.replace(junk, '') + return proc + def canon_processor(archinfo, proc): + proc = fixup_proc_name(proc) + for ainfo in archinfo.values(): if ainfo.basename == proc or proc in ainfo.aliases: return (ainfo.basename, ainfo.basename) @@ -560,12 +625,7 @@ def guess_processor(archinfo): if base_proc == '': raise Exception('Could not determine target CPU; set with --cpu') - full_proc = platform.processor().lower().replace(' ', '') - for junk in ['(tm)', '(r)']: - full_proc = full_proc.replace(junk, '') - - if full_proc == '': - full_proc = base_proc + full_proc = fixup_proc_name(platform.processor()) or base_proc for ainfo in archinfo.values(): if ainfo.basename == base_proc or base_proc in ainfo.aliases: @@ -704,7 +764,7 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): options.arch, options.cpu), - 'lib_opt': cc.lib_opt_flags, + 'lib_opt': cc.library_opt_flags(options.debug_build), 'mach_opt': cc.mach_opts(options.arch, options.cpu), 'check_opt': cc.check_opt_flags, 'lang_flags': cc.lang_flags + options.extra_flags, @@ -725,7 +785,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), @@ -745,6 +806,14 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): build_commands(build_config.check_sources, build_config.checkobj_dir, 'CHECK')), + 'python_objs': makefile_list( + objectfile_list(build_config.python_sources, + build_config.pyobject_dir)), + + 'python_build_cmds': '\n'.join( + build_commands(build_config.python_sources, + build_config.pyobject_dir, 'PYTHON')), + 'ar_command': cc.ar_command or osinfo.ar_command, 'ranlib_command': osinfo.ranlib_command(), 'install_cmd_exec': osinfo.install_cmd_exec, @@ -766,6 +835,8 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): 'mod_list': '\n'.join(['%s (%s)' % (m.basename, m.realname) for m in sorted(modules)]), + + 'python_version': '.'.join(map(str, sys.version_info[0:2])) } """ @@ -957,10 +1028,8 @@ def setup_build(build_config, options, template_vars): except OSError, e: logging.debug('Error while removing build dir: %s' % (e)) - for dirs in [build_config.checkobj_dir, - build_config.libobj_dir, - build_config.full_include_dir]: - os.makedirs(dirs) + for dir in build_config.build_dirs(): + os.makedirs(dir) makefile_template = os.path.join( options.makefile_dir, @@ -979,6 +1048,10 @@ def setup_build(build_config, options, template_vars): templates_to_proc[os.path.join(options.build_data, template)] = \ os.path.join(build_config.build_dir, sink) + if options.boost_python: + templates_to_proc[ + os.path.join(options.makefile_dir, 'python.in')] = 'Makefile.python' + for (template, sink) in templates_to_proc.items(): try: f = open(sink, 'w') diff --git a/doc/building.tex b/doc/building.tex index aa4435c14..f58786e76 100644 --- a/doc/building.tex +++ b/doc/building.tex @@ -13,7 +13,7 @@ \title{\textbf{Botan Build Guide}} \author{Jack Lloyd \\ \texttt{[email protected]}} -\date{2008-11-24} +\date{2009-10-09} \newcommand{\filename}[1]{\texttt{#1}} \newcommand{\module}[1]{\texttt{#1}} @@ -41,61 +41,58 @@ POSIX (such as VMS, MacOS 9, OS/390, OS/400, ...) are not supported by the build system, primarily due to lack of access. Please contact the maintainer if you would like to build Botan on such a system. -Botan's build is controlled by configure.pl, which is a Perl -script. Perl 5.6 or later is required. +Botan's build is controlled by configure.py, which is a Python +script. Python 2.4 or later is required. \section{For the Impatient} \begin{verbatim} -$ ./configure.pl [--prefix=/some/directory] +$ ./configure.py [--prefix=/some/directory] $ make $ make install \end{verbatim} Or using \verb|nmake|, if you're compiling on Windows with Visual C++. On platforms that do not understand the '\#!' convention for -beginning script files, or that have Perl installed in an unusual -spot, you might need to prefix the \texttt{configure.pl} command with -\texttt{perl} or \texttt{/path/to/perl}. +beginning script files, or that have Python installed in an unusual +spot, you might need to prefix the \texttt{configure.py} command with +\texttt{python} or \texttt{/path/to/python}. \section{Building the Library} -The first step is to run \filename{configure.pl}, which is a Perl +The first step is to run \filename{configure.py}, which is a Python script that creates various directories, config files, and a Makefile -for building everything. The script requires at least Perl 5.6; any -later version should also work. +for building everything. The script requires at least Python 2.4; any +later version of Python 2.x should also work. The script will attempt to guess what kind of system you are trying to compile for (and will print messages telling you what it guessed). You can override this process by passing the options \verb|--cc|, -\verb|--os|, and \verb|--cpu| -- acceptable values are printed if -you run \verb|configure.pl| with \verb|--help|. +\verb|--os|, and \verb|--cpu|. You can pass basically anything reasonable with \verb|--cpu|: the script knows about a large number of different architectures, their -sub-models, and common aliases for them. The script does not display -all the possibilities in its help message because there are simply too -many entries. You should only select the 64-bit version of a CPU (such -as ``sparc64'' or ``mips64'') if your operating system knows how to -handle 64-bit object code -- a 32-bit kernel on a 64-bit CPU will -generally not like 64-bit code. +sub-models, and common aliases for them. You should only select the +64-bit version of a CPU (such as ``sparc64'' or ``mips64'') if your +operating system knows how to handle 64-bit object code -- a 32-bit +kernel on a 64-bit CPU will generally not like 64-bit code. By default the script tries to figure out what will work on your -system, and use that. It will print a display at the end showing -which algorithms have and have not been abled. For instance on one -system we might see the line: +system, and use that. It will print a display at the end showing which +algorithms have and have not been enabled. For instance on one system +we might see lines like: \begin{verbatim} - (loading): entropy: [beos_stats] buf_es [cryptoapi_rng] - dev_random egd proc_walk unix_procs [win32_stats] + INFO: Skipping mod because CPU incompatible - asm_amd64 mp_amd64 mp_asm64 sha1_amd64 + INFO: Skipping mod because OS incompatible - cryptoapi_rng win32_stats + INFO: Skipping mod because compiler incompatible - mp_ia32_msvc + INFO: Skipping mod because loaded on request only - bzip2 gnump openssl qt_mutex zlib \end{verbatim} -The names listed in brackets are disabled, the others are -enabled. Here we see the list of entropy sources which are going to be -compiled into Botan. Since this particular line comes when Botan was -configuring for a Linux system, the Win32 and BeOS specific modules -were disabled, while modules that use Unix APIs and /dev/random are -built. +The ones that are 'loaded on request only' have to be explicitly asked +for, because they rely on third party libraries which your system +might not have. For instance to enable zlib support, add +\verb|--with-zlib| to your invocation of \verb|configure.py|. You can control which algorithms and modules are built using the options ``\verb|--enable-modules=MODS|'' and @@ -104,20 +101,6 @@ options ``\verb|--enable-modules=MODS|'' and Modules not listed on the command line will simply be loaded if needed or if configured to load by default. -Not all OSes or CPUs have specific support in -\filename{configure.pl}. If the CPU architecture of your system isn't -supported by \filename{configure.pl}, use 'generic'. This setting -disables machine-specific optimization flags. Similarly, setting OS to -'generic' disables things which depend greatly on OS support -(specifically, shared libraries). - -However, it's impossible to guess which options to give to a system -compiler. Thus, if you want to compile Botan with a compiler which -\filename{configure.pl} does not support, you will need to tell it how -that compiler works. This is done by adding a new file in the -directory \filename{src/build-data/cc}; the existing files should put you -in the right direction. - The script tries to guess what kind of makefile to generate, and it almost always guesses correctly (basically, Visual C++ uses NMAKE with Windows commands, and everything else uses Unix make with POSIX @@ -128,14 +111,12 @@ commonly used by Windows compilers. To add a new variant (eg, a build script for VMS), you will need to create a new template file in \filename{src/build-data/makefile}. -\pagebreak - \subsection{POSIX / Unix} The basic build procedure on Unix and Unix-like systems is: \begin{verbatim} - $ ./configure.pl [--enable-modules=<list>] [--cc=CC] + $ ./configure.py [--enable-modules=<list>] [--cc=CC] $ make # You may need to set your LD_LIBRARY_PATH or equivalent for ./check to run $ make check # optional, but a good idea @@ -148,9 +129,9 @@ found within your PATH. The \verb|make install| target has a default directory in which it will install Botan (typically \verb|/usr/local|). You can override this by using the \texttt{--prefix} argument to -\filename{configure.pl}, like so: +\filename{configure.py}, like so: -\verb|./configure.pl --prefix=/opt <other arguments>| +\verb|./configure.py --prefix=/opt <other arguments>| On some systems shared libraries might not be immediately visible to the runtime linker. For example, on Linux you may have to edit @@ -163,10 +144,10 @@ to include the directory that the Botan libraries were installed into. The situation is not much different here. We'll assume you're using Visual C++ (for Cygwin, the Unix instructions are probably more relevant). You need to -have a copy of Perl installed, and have both Perl and Visual C++ in your path. +have a copy of Python installed, and have both Python and Visual C++ in your path. \begin{verbatim} - > perl configure.pl --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] + > python configure.py --cc=msvc (or --cc=gcc for MinGW) [--cpu=CPU] > nmake > nmake check # optional, but recommended \end{verbatim} @@ -244,7 +225,7 @@ environment in a different directory. \subsection{Local Configuration} You may want to do something peculiar with the configuration; to -support this there is a flag to \filename{configure.pl} called +support this there is a flag to \filename{configure.py} called \texttt{--with-local-config=<file>}. The contents of the file are inserted into \filename{build/build.h} which is (indirectly) included into every Botan header and source file. @@ -395,4 +376,70 @@ is less of a problem - only the developer needs to worry about it. As long as they can remember where they installed Botan, they just have to set the appropriate flags in their Makefile/project file. +\pagebreak + +\section{Language Wrappers} + +\subsection{Building the Python wrappers} + +The Python wrappers for Botan use Boost.Python, so you must have Boost +installed. To build the wrappers, add the flag + +\verb|--use-boost-python| + +to \verb|configure.py|. This will create a second makefile, +\verb|Makefile.python|, with instructions for building the Python +module. After building the library, execute + +\begin{verbatim} +$ make -f Makefile.python +\end{verbatim} + +to build the module. Currently only Unix systems are supported, and +the Makefile assumes that the version of Python you want to build +against is the same one you used to run \verb|configure.py|. + +To install the module, use the \verb|install| target. + +Examples of using the Python module can be seen in \filename{doc/python} + +\subsection{Building the Perl XS wrappers} + +To build the Perl XS wrappers, change your directory to +\filename{src/wrap/perl-xs} and run \verb|perl Makefile.PL|, then run +\verb|make| to build the module and \verb|make test| to run the test +suite. + +\begin{verbatim} +$ perl Makefile.PL +Checking if your kit is complete... +Looks good +Writing Makefile for Botan +$ make +cp Botan.pm blib/lib/Botan.pm +AutoSplitting blib/lib/Botan.pm (blib/lib/auto/Botan) +/usr/bin/perl5.8.8 /usr/lib64/perl5/5.8.8/ExtUtils/xsubpp [...] +g++ -c -Wno-write-strings -fexceptions -g [...] +Running Mkbootstrap for Botan () +chmod 644 Botan.bs +rm -f blib/arch/auto/Botan/Botan.so +g++ -shared Botan.o -o blib/arch/auto/Botan/Botan.so \ + -lbotan -lbz2 -lpthread -lrt -lz \ + +chmod 755 blib/arch/auto/Botan/Botan.so +cp Botan.bs blib/arch/auto/Botan/Botan.bs +chmod 644 blib/arch/auto/Botan/Botan.bs +Manifying blib/man3/Botan.3pm +$ make test +PERL_DL_NONLAZY=1 /usr/bin/perl5.8.8 [...] +t/base64......ok +t/filt........ok +t/hex.........ok +t/oid.........ok +t/pipe........ok +t/x509cert....ok +All tests successful. +Files=6, Tests=83, 0 wallclock secs ( 0.08 cusr + 0.02 csys = 0.10 CPU) +\end{verbatim} + \end{document} diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile index d854c81d8..44fcfeea5 100644 --- a/doc/examples/GNUmakefile +++ b/doc/examples/GNUmakefile @@ -2,8 +2,8 @@ BOTAN_CONFIG = botan-config CXX = g++ -CFLAGS = -O2 -ansi -W -Wall $(shell $(BOTAN_CONFIG) --cflags) -LIBS = $(shell $(BOTAN_CONFIG) --libs) +CFLAGS = -O2 -ansi -W -Wall -I../../build/include +LIBS = -L../.. -lbotan SRCS=$(wildcard *.cpp) diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp index 37ef1104d..cc43fade0 100644 --- a/doc/examples/bench.cpp +++ b/doc/examples/bench.cpp @@ -7,26 +7,6 @@ using namespace Botan; #include <iostream> -double best_speed(const std::string& algorithm, - u32bit milliseconds, - RandomNumberGenerator& rng, - Timer& timer) - { - std::map<std::string, double> speeds = - algorithm_benchmark(algorithm, milliseconds, - timer, rng, - global_state().algorithm_factory()); - - double best_time = 0; - - for(std::map<std::string, double>::const_iterator i = speeds.begin(); - i != speeds.end(); ++i) - if(i->second > best_time) - best_time = i->second; - - return best_time; - } - const std::string algos[] = { "AES-128", "AES-192", @@ -62,7 +42,6 @@ const std::string algos[] = { "FORK-256", "GOST-34.11", "HAS-160", - "HAS-V", "MD2", "MD4", "MD5", @@ -81,18 +60,40 @@ const std::string algos[] = { "", }; -int main() +void benchmark_algo(const std::string& algo, + RandomNumberGenerator& rng) + { + u32bit milliseconds = 3000; + Default_Benchmark_Timer timer; + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::map<std::string, double> speeds = + algorithm_benchmark(algo, milliseconds, timer, rng, af); + + std::cout << algo << ":"; + + for(std::map<std::string, double>::const_iterator i = speeds.begin(); + i != speeds.end(); ++i) + { + std::cout << " " << i->second << " [" << i->first << "]"; + } + std::cout << "\n"; + } + +int main(int argc, char* argv[]) { LibraryInitializer init; - u32bit milliseconds = 1000; AutoSeeded_RNG rng; - Default_Benchmark_Timer timer; - for(u32bit i = 0; algos[i] != ""; ++i) + if(argc == 1) // no args, benchmark everything + { + for(u32bit i = 0; algos[i] != ""; ++i) + benchmark_algo(algos[i], rng); + } + else { - std::string algo = algos[i]; - std::cout << algo << ' ' - << best_speed(algo, milliseconds, rng, timer) << "\n"; + for(int i = 1; argv[i]; ++i) + benchmark_algo(argv[i], rng); } } diff --git a/doc/examples/cms_dec.cpp b/doc/examples/cms_dec.cpp index 3fa285395..de4d732f0 100644 --- a/doc/examples/cms_dec.cpp +++ b/doc/examples/cms_dec.cpp @@ -10,7 +10,7 @@ int main(int argc, char* argv[]) { if(argc != 2) { - printf("Usage: %s <filename>\n", argv[0]); + std::cout << "Usage: " << argv[0] << " <filename>\n"; return 1; } diff --git a/doc/examples/cpuid.cpp b/doc/examples/cpuid.cpp new file mode 100644 index 000000000..59940b500 --- /dev/null +++ b/doc/examples/cpuid.cpp @@ -0,0 +1,15 @@ +#include <stdio.h> + +#include <botan/cpuid.h> + +using namespace Botan; + +int main() + { + printf("Cache line size: %d\n", CPUID::cache_line_size()); + printf("RDTSC: %d\n", CPUID::has_rdtsc()); + printf("SSE2 %d\n", CPUID::has_sse2()); + printf("SSSE3 %d\n", CPUID::has_ssse3()); + printf("SSE41 %d\n", CPUID::has_sse41()); + printf("SSE42 %d\n", CPUID::has_sse42()); + } diff --git a/doc/examples/package.cpp b/doc/examples/package.cpp new file mode 100644 index 000000000..866dd7e96 --- /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/examples/tss.cpp b/doc/examples/tss.cpp new file mode 100644 index 000000000..1881ffe24 --- /dev/null +++ b/doc/examples/tss.cpp @@ -0,0 +1,38 @@ +#include <botan/botan.h> +#include <botan/tss.h> +#include <iostream> +#include <stdio.h> + +namespace { + +void print(const Botan::SecureVector<Botan::byte>& r) + { + for(Botan::u32bit i = 0; i != r.size(); ++i) + printf("%02X", r[i]); + printf("\n"); + } + +} + +int main() + { + using namespace Botan; + + LibraryInitializer init; + + AutoSeeded_RNG rng; + + byte id[16]; + for(int i = 0; i != 16; ++i) + id[i] = i; + + const byte S2[] = { 0xDE, 0xAD, 0xCA, 0xFE, 0xBA, 0xBE, 0xBE, 0xEF }; + + std::vector<RTSS_Share> shares = + RTSS_Share::split(4, 6, S2, sizeof(S2), id, rng); + + for(size_t i = 0; i != shares.size(); ++i) + std::cout << i << " = " << shares[i].to_string() << "\n"; + + print(RTSS_Share::reconstruct(shares)); + } diff --git a/doc/log.txt b/doc/log.txt index 9ccb286ca..1d219eb1c 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,4 +1,29 @@ +* 1.9.2-dev, ????-??-?? + +* 1.9.1, 2009-10-23 + - Better support for Python and Perl wrappers + - Add an implementation of Blue Midnight Wish (Round 2 tweak version) + - Modify Skein-512 to match the tweaked 1.2 specification + - Add threshold secret sharing (draft-mcgrew-tss-02) + - Add runtime cpu feature detection for x86/x86-64 + - Add code for general runtime self testing for hashes, MACs, and ciphers + - Optimize XTEA; twice as fast as before on Core2 and Opteron + - Convert CTR_BE and OFB from filters to stream ciphers + - New parsing code for SCAN algorithm names + - Enable SSE2 optimizations under Visual C++ + - Remove all use of C++ exception specifications + - Add support for GNU/Hurd and Clang/LLVM + +* 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 - Fix use of inline asm for access to x86 bswap function diff --git a/doc/python.tex b/doc/python.tex new file mode 100644 index 000000000..afdd66b6a --- /dev/null +++ b/doc/python.tex @@ -0,0 +1,68 @@ +\documentclass{article} + +\setlength{\textwidth}{6.5in} % 1 inch side margins +\setlength{\textheight}{9in} % ~1 inch top and bottom margins + +\setlength{\headheight}{0in} +\setlength{\topmargin}{0in} +\setlength{\headsep}{0in} + +\setlength{\oddsidemargin}{0in} +\setlength{\evensidemargin}{0in} + +\title{\textbf{Botan Python Interface Documentation}} +\author{Jack Lloyd \\ + \texttt{[email protected]}} +\date{2009/10/10} + +\newcommand{\filename}[1]{\texttt{#1}} +\newcommand{\manpage}[2]{\texttt{#1}(#2)} + +\newcommand{\macro}[1]{\texttt{#1}} + +\newcommand{\function}[1]{\textbf{#1}} +\newcommand{\type}[1]{\texttt{#1}} +\renewcommand{\arg}[1]{\textsl{#1}} +\newcommand{\variable}[1]{\textsl{#1}} + +\begin{document} + +\maketitle + +\tableofcontents + +\parskip=5pt +\pagebreak + +\section{Ciphers} + +Botan's Python interface provides a generic interface to any cipher +supported by the library. The class \type{botan.Cipher} takes three +arguments, all strings: first, the name of the algorith, second the +direction (which can be either ``encrypt'' or ``decrypt''), and +lastly, the key to use. For instance + +\begin{verbatim} + encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) +\end{verbatim} + +creates an object that will encrypt and authenticate messages using +the EAX mode of operation using the AES cipher. To use this object, +call the \function{cipher} function with two arguments - the input +to encrypt, and the IV to use: + +\begin{verbatim} + ciphertext = encryptor.cipher(input, salt) +\end{verbatim} + + +\subsection{Cryptobox} + + +\subsection{RNGs} + +\section{RSA} + + + +\end{document} diff --git a/doc/python/cipher.py b/doc/python/cipher.py new file mode 100755 index 000000000..1be2759ae --- /dev/null +++ b/doc/python/cipher.py @@ -0,0 +1,44 @@ +#!/usr/bin/python + +import botan +import sys + +def encrypt(input, passphrase): + rng = botan.RandomNumberGenerator() + + # Use as both EAX IV and PBKDF2 salt + salt = rng.gen_random(10) + + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) + + ciphertext = encryptor.cipher(input, salt) + return (ciphertext, salt) + +def decrypt(input, salt, passphrase): + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + decryptor = botan.Cipher("AES-128/EAX", "decrypt", key) + + return decryptor.cipher(input, salt) + +def main(args = None): + if args is None: + args = sys.argv + + passphrase = args[1] + input = ''.join(open(args[2]).readlines()) + + (ciphertext, salt) = encrypt(input, passphrase) + + print decrypt(ciphertext, salt, passphrase) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/doc/python/cryptobox.py b/doc/python/cryptobox.py new file mode 100755 index 000000000..1968b40e1 --- /dev/null +++ b/doc/python/cryptobox.py @@ -0,0 +1,34 @@ +#!/usr/bin/python + +import sys +import botan + +def main(args = None): + if args is None: + args = sys.argv + + if len(args) != 3: + raise Exception("Bad usage") + + password = args[1] + input = ''.join(open(args[2]).readlines()) + + rng = botan.RandomNumberGenerator() + + ciphertext = botan.cryptobox_encrypt(input, password, rng) + + print ciphertext + + plaintext = '' + + try: + plaintext = botan.cryptobox_decrypt(ciphertext, password + 'FAIL') + except Exception, e: + print "Oops -- ", e + + plaintext = botan.cryptobox_decrypt(ciphertext, password) + + print plaintext + +if __name__ == '__main__': + sys.exit(main()) diff --git a/wrappers/boost-python/nisttest.py b/doc/python/nisttest.py index 3ea8fda0f..3ea8fda0f 100755 --- a/wrappers/boost-python/nisttest.py +++ b/doc/python/nisttest.py diff --git a/wrappers/boost-python/results.txt b/doc/python/results.txt index 7a3824001..7a3824001 100644 --- a/wrappers/boost-python/results.txt +++ b/doc/python/results.txt diff --git a/wrappers/boost-python/rng_test.py b/doc/python/rng_test.py index 06c79b84e..06c79b84e 100755 --- a/wrappers/boost-python/rng_test.py +++ b/doc/python/rng_test.py diff --git a/doc/python/rsa.py b/doc/python/rsa.py new file mode 100755 index 000000000..15ffcffa3 --- /dev/null +++ b/doc/python/rsa.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +import botan + +rng = botan.RandomNumberGenerator() + +rsa_priv = botan.RSA_PrivateKey(768, rng) + +print rsa_priv.to_string() +print int(rsa_priv.get_N()) +print int(rsa_priv.get_E()) + + +rsa_pub = botan.RSA_PublicKey(rsa_priv) + +key = rng.gen_random(20) + +ciphertext = rsa_pub.encrypt(key, 'EME1(SHA-1)', rng) + +print ciphertext.encode('hex') + +plaintext = rsa_priv.decrypt(ciphertext, 'EME1(SHA-1)') + +print plaintext == key + + +signature = rsa_priv.sign(key, 'EMSA4(SHA-256)', rng) + +key = key.replace('a', 'b') + +print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') diff --git a/configure.pl b/doc/scripts/configure.pl index 9415d5a42..9415d5a42 100755 --- a/configure.pl +++ b/doc/scripts/configure.pl diff --git a/doc/scripts/dist.sh b/doc/scripts/dist.sh index 9629446cf..2b03b1a71 100755 --- a/doc/scripts/dist.sh +++ b/doc/scripts/dist.sh @@ -3,10 +3,16 @@ # This is probably only useful if run on my machine, which is not # exactly ideal -SELECTOR=h:net.randombit.botan.1_8 +# Make that limitation explicit +if [ $(hostname -s) != 'chihiro' ]; then + echo "This script probably won't work on this machine without fixes" + exit 1 +fi + +SELECTOR=h:net.randombit.botan KEY_ID=EFBADFBC -MTN_DB=/storage/mtn/botan.mtn -WEB_DIR=~/projects/www +MTN_DB=$HOME/var/mtn/botan.mtn +WEB_DIR=/var/www/randombit.net/files/botan/v1.9 DIST_DIR=~/Botan-dist # You shouldn't have to change anything after this @@ -26,7 +32,7 @@ rm -f .mtn-ignore # Build docs cd doc -for doc in api tutorial building +for doc in api tutorial building python do latex $doc.tex latex $doc.tex @@ -60,5 +66,5 @@ read -a PASSWORD -p "Enter PGP password (or ^C to skip signatures): " echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tgz echo $PASSWORD | gpg --batch --armor -b --passphrase-fd 0 -u $KEY_ID Botan-$VERSION.tbz -mv Botan-$VERSION.tgz* $WEB_DIR/files/botan/v1.8 -mv Botan-$VERSION.tbz* $WEB_DIR/files/botan/v1.8 +mv Botan-$VERSION.tgz* $WEB_DIR +mv Botan-$VERSION.tbz* $WEB_DIR diff --git a/readme.txt b/readme.txt index 36f2d2043..644c6a4a8 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Botan 1.8.8-dev 2009-??-?? +Botan 1.9.2-dev, ????-??-?? Botan is a C++ class library for performing a wide variety of cryptographic operations. diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h index 17ea9964a..08b25cd47 100644 --- a/src/algo_factory/algo_cache.h +++ b/src/algo_factory/algo_cache.h @@ -1,5 +1,8 @@ -/** +/* * An algorithm cache (used by Algorithm_Factory) +* (C) 2008-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index 269c58c3b..22915d97c 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 */ @@ -62,6 +62,10 @@ const T* factory_prototype(const std::string& algo_spec, return cache_hit; SCAN_Name scan_name(algo_spec); + + if(scan_name.cipher_mode() != "") + return 0; + for(u32bit i = 0; i != engines.size(); ++i) { if(provider == "" || engines[i]->provider_name() == provider) diff --git a/src/alloc/mem_pool/mem_pool.cpp b/src/alloc/mem_pool/mem_pool.cpp index 38e0c3285..e30a7b98a 100644 --- a/src/alloc/mem_pool/mem_pool.cpp +++ b/src/alloc/mem_pool/mem_pool.cpp @@ -8,7 +8,7 @@ */ #include <botan/mem_pool.h> -#include <botan/util.h> +#include <botan/rounding.h> #include <botan/mem_ops.h> #include <algorithm> #include <exception> @@ -42,7 +42,7 @@ Pooling_Allocator::Memory_Block::Memory_Block(void* buf) * See if ptr is contained by this block */ bool Pooling_Allocator::Memory_Block::contains(void* ptr, - u32bit length) const throw() + u32bit length) const { return ((buffer <= ptr) && (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE)); @@ -51,7 +51,7 @@ bool Pooling_Allocator::Memory_Block::contains(void* ptr, /* * Allocate some memory, if possible */ -byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) throw() +byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) { if(n == 0 || n > BITMAP_SIZE) return 0; @@ -91,7 +91,7 @@ byte* Pooling_Allocator::Memory_Block::alloc(u32bit n) throw() /* * Mark this memory as free, if we own it */ -void Pooling_Allocator::Memory_Block::free(void* ptr, u32bit blocks) throw() +void Pooling_Allocator::Memory_Block::free(void* ptr, u32bit blocks) { clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE); diff --git a/src/alloc/mem_pool/mem_pool.h b/src/alloc/mem_pool/mem_pool.h index a57800972..51571405e 100644 --- a/src/alloc/mem_pool/mem_pool.h +++ b/src/alloc/mem_pool/mem_pool.h @@ -44,9 +44,9 @@ class BOTAN_DLL Pooling_Allocator : public Allocator static u32bit bitmap_size() { return BITMAP_SIZE; } static u32bit block_size() { return BLOCK_SIZE; } - bool contains(void*, u32bit) const throw(); - byte* alloc(u32bit) throw(); - void free(void*, u32bit) throw(); + bool contains(void*, u32bit) const; + byte* alloc(u32bit); + void free(void*, u32bit); bool operator<(const Memory_Block& other) const { diff --git a/src/alloc/system_alloc/defalloc.cpp b/src/alloc/system_alloc/defalloc.cpp index 8791c74e4..b1b338d71 100644 --- a/src/alloc/system_alloc/defalloc.cpp +++ b/src/alloc/system_alloc/defalloc.cpp @@ -7,7 +7,7 @@ #include <botan/defalloc.h> #include <botan/libstate.h> -#include <botan/util.h> +#include <botan/mlock.h> #include <cstdlib> #include <cstring> 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..37bad46c8 --- /dev/null +++ b/src/aont/package.cpp @@ -0,0 +1,120 @@ +/* +* Rivest's Package Tranform +* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/package.h> +#include <botan/filters.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); + + Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); + + 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); + } + + Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key)); + + 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/asn1/asn1_tm.cpp b/src/asn1/asn1_tm.cpp index f85ea128b..09bc4d347 100644 --- a/src/asn1/asn1_tm.cpp +++ b/src/asn1/asn1_tm.cpp @@ -10,28 +10,10 @@ #include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> -#include <ctime> +#include <botan/timer.h> namespace Botan { -namespace { - -/* -* Convert a time_t to a struct tm -*/ -std::tm get_tm(u64bit timer) - { - std::time_t time_val = static_cast<std::time_t>(timer); - - std::tm* tm_p = std::gmtime(&time_val); - if(tm_p == 0) - throw Encoding_Error("X509_Time: gmtime could not encode " + - to_string(timer)); - return (*tm_p); - } - -} - /* * Create an X509_Time */ @@ -45,7 +27,7 @@ X509_Time::X509_Time(const std::string& time_str) */ X509_Time::X509_Time(u64bit timer) { - std::tm time_info = get_tm(timer); + std::tm time_info = time_t_to_tm(timer); year = time_info.tm_year + 1900; month = time_info.tm_mon + 1; diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp index 01e3b94f3..41c9cd10c 100644 --- a/src/benchmark/benchmark.cpp +++ b/src/benchmark/benchmark.cpp @@ -11,7 +11,6 @@ #include <botan/stream_cipher.h> #include <botan/hash.h> #include <botan/mac.h> -#include <botan/util.h> #include <memory> namespace Botan { @@ -55,10 +54,11 @@ bench_block_cipher(BlockCipher* block_cipher, const u32bit in_blocks = buf_len / block_cipher->BLOCK_SIZE; + block_cipher->set_key(buf, block_cipher->MAXIMUM_KEYLENGTH); + 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; @@ -81,9 +81,11 @@ bench_stream_cipher(StreamCipher* stream_cipher, u64bit nanoseconds_used = 0; u64bit reps = 0; + stream_cipher->set_key(buf, stream_cipher->MAXIMUM_KEYLENGTH); + while(nanoseconds_used < nanoseconds_max) { - stream_cipher->encrypt(buf, buf_len); + stream_cipher->cipher1(buf, buf_len); ++reps; nanoseconds_used = timer.clock() - start; } diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 9072b507b..7ba8136ec 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; + } } /** @@ -246,7 +258,7 @@ AES::AES(u32bit key_size) : BlockCipher(16, key_size) /** * Clear memory of sensitive data */ -void AES::clear() throw() +void AES::clear() { EK.clear(); DK.clear(); diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index 05e2e3123..229ce307c 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/aes/info.txt b/src/block/aes/info.txt index 2803ccc4e..0e11603bb 100644 --- a/src/block/aes/info.txt +++ b/src/block/aes/info.txt @@ -1,11 +1,3 @@ realname "AES" define AES - -load_on auto - -<add> -aes.cpp -aes.h -aes_tab.cpp -</add> diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h index 01c45af04..1dcdde7c7 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 @@ -80,7 +87,7 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm /** * Zeroize internal state */ - virtual void clear() throw() = 0; + virtual void clear() = 0; BlockCipher(u32bit block_size, u32bit key_min, @@ -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..d0b182a84 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; + } } /* @@ -116,7 +128,7 @@ void Blowfish::generate_sbox(u32bit Box[], u32bit size, /* * Clear memory of sensitive data */ -void Blowfish::clear() throw() +void Blowfish::clear() { P.copy(P_INIT, 18); S.copy(S_INIT, 1024); diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index f0f26418d..5419308ca 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/blowfish/info.txt b/src/block/blowfish/info.txt index 0a9d2adc2..c63560989 100644 --- a/src/block/blowfish/info.txt +++ b/src/block/blowfish/info.txt @@ -1,11 +1,3 @@ realname "Blowfish" define BLOWFISH - -load_on auto - -<add> -blfs_tab.cpp -blowfish.cpp -blowfish.h -</add> 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..caffb97ea 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 clear() throw() { MK.clear(); RK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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..0db3682ba 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 clear() throw() { MK.clear(); RK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/cast/info.txt b/src/block/cast/info.txt index 73d3f900f..b9259042d 100644 --- a/src/block/cast/info.txt +++ b/src/block/cast/info.txt @@ -1,13 +1,3 @@ realname "CAST" define CAST - -load_on auto - -<add> -cast128.cpp -cast128.h -cast256.cpp -cast256.h -cast_tab.cpp -</add> diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp index 37520e0fc..05287304f 100644 --- a/src/block/des/des.cpp +++ b/src/block/des/des.cpp @@ -139,51 +139,62 @@ 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 +208,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..b28990178 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 clear() throw() { round_key.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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 clear() throw() { round_key.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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..89664d064 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 clear() throw() { des.clear(); K1.clear(); K2.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/des/info.txt b/src/block/des/info.txt index ed05979c9..6eec591a0 100644 --- a/src/block/des/info.txt +++ b/src/block/des/info.txt @@ -1,13 +1,3 @@ realname "DES" define DES - -load_on auto - -<add> -des.cpp -des.h -des_tab.cpp -desx.h -desx.cpp -</add> 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..bf6f8178b 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -44,7 +44,10 @@ class GOST_28147_89_Params class BOTAN_DLL GOST_28147_89 : public BlockCipher { public: - void clear() throw() { EK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { EK.clear(); } std::string name() const { return "GOST-28147-89"; } BlockCipher* clone() const { return new GOST_28147_89(SBOX); } @@ -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/gost_28147/info.txt b/src/block/gost_28147/info.txt index 6e187fd48..9b24d1e22 100644 --- a/src/block/gost_28147/info.txt +++ b/src/block/gost_28147/info.txt @@ -1,10 +1,3 @@ realname "GOST 28147-89" define GOST_28147_89 - -load_on auto - -<add> -gost_28147.cpp -gost_28147.h -</add> 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..c1a79f423 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 clear() throw() { EK.clear(); DK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/idea/info.txt b/src/block/idea/info.txt index 2da3ffb43..f11b3d224 100644 --- a/src/block/idea/info.txt +++ b/src/block/idea/info.txt @@ -1,10 +1,3 @@ realname "IDEA" define IDEA - -load_on auto - -<add> -idea.cpp -idea.h -</add> diff --git a/src/block/info.txt b/src/block/info.txt index ff48fb04a..f5840bf79 100644 --- a/src/block/info.txt +++ b/src/block/info.txt @@ -1,13 +1,7 @@ realname "Block Ciphers" -load_on auto - define BLOCK_CIPHER -<add> -block_cipher.h -</add> - <requires> sym_algo </requires> diff --git a/src/block/kasumi/info.txt b/src/block/kasumi/info.txt index 8ea879b6d..e310488b3 100644 --- a/src/block/kasumi/info.txt +++ b/src/block/kasumi/info.txt @@ -1,10 +1,3 @@ realname "Kasumi" define KASUMI - -load_on auto - -<add> -kasumi.cpp -kasumi.h -</add> 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..c3db1cb05 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 clear() throw() { EK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/lion/info.txt index 81ef58511..64f2989b1 100644 --- a/src/block/lion/info.txt +++ b/src/block/lion/info.txt @@ -2,13 +2,6 @@ realname "Lion" define LION -load_on auto - -<add> -lion.cpp -lion.h -</add> - <requires> hash stream diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp index c7cdf6d13..e71091258 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->cipher(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->cipher1(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->cipher(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->cipher1(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; + } } /* @@ -83,7 +95,7 @@ BlockCipher* Lion::clone() const /* * Clear memory of sensitive data */ -void Lion::clear() throw() +void Lion::clear() { hash->clear(); cipher->clear(); diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h index 5bc4e72c0..f24acdb72 100644 --- a/src/block/lion/lion.h +++ b/src/block/lion/lion.h @@ -20,15 +20,16 @@ namespace Botan { class BOTAN_DLL Lion : public BlockCipher { public: - void clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); std::string name() const; BlockCipher* clone() const; 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/info.txt b/src/block/lubyrack/info.txt index a478526f4..d915781d8 100644 --- a/src/block/lubyrack/info.txt +++ b/src/block/lubyrack/info.txt @@ -2,13 +2,6 @@ realname "Luby-Rackoff" define LUBY_RACKOFF -load_on auto - -<add> -lubyrack.cpp -lubyrack.h -</add> - <requires> hash </requires> diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp index a9d2b1db2..2003d2a89 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; + } } /* @@ -80,7 +92,7 @@ void LubyRackoff::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void LubyRackoff::clear() throw() +void LubyRackoff::clear() { K1.clear(); K2.clear(); diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h index ebde31304..7249cf157 100644 --- a/src/block/lubyrack/lubyrack.h +++ b/src/block/lubyrack/lubyrack.h @@ -19,16 +19,18 @@ namespace Botan { class BOTAN_DLL LubyRackoff : public BlockCipher { public: - void clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); std::string name() const; BlockCipher* clone() const; 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/info.txt b/src/block/mars/info.txt index b0ad8af9c..ec958eaf5 100644 --- a/src/block/mars/info.txt +++ b/src/block/mars/info.txt @@ -1,11 +1,3 @@ realname "MARS" define MARS - -load_on auto - -<add> -mars.cpp -mars.h -mars_tab.cpp -</add> 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..8173fb984 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 clear() throw() { EK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/misty1/info.txt index d45058bd4..38087c83d 100644 --- a/src/block/misty1/info.txt +++ b/src/block/misty1/info.txt @@ -1,10 +1,3 @@ realname "MISTY-1" define MISTY1 - -load_on auto - -<add> -misty1.cpp -misty1.h -</add> 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..000830915 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 clear() throw() { EK.clear(); DK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/noekeon/info.txt index 8025c2073..6e940bb62 100644 --- a/src/block/noekeon/info.txt +++ b/src/block/noekeon/info.txt @@ -1,10 +1,3 @@ realname "Noekeon" define NOEKEON - -load_on auto - -<add> -noekeon.cpp -noekeon.h -</add> diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp index 90eb9ad2b..0bfce1882 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; + } } /* @@ -189,7 +201,7 @@ void Noekeon::key_schedule(const byte key[], u32bit) /* * Clear memory of sensitive data */ -void Noekeon::clear() throw() +void Noekeon::clear() { EK.clear(); DK.clear(); diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 893892446..4532c1be2 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/info.txt b/src/block/rc2/info.txt index 099141de7..7ec018422 100644 --- a/src/block/rc2/info.txt +++ b/src/block/rc2/info.txt @@ -1,10 +1,3 @@ realname "RC2" define RC2 - -load_on auto - -<add> -rc2.cpp -rc2.h -</add> 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..c6e4946f9 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(); } + void clear() { 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/info.txt b/src/block/rc5/info.txt index 4a150c3b0..2032b406f 100644 --- a/src/block/rc5/info.txt +++ b/src/block/rc5/info.txt @@ -1,10 +1,3 @@ realname "RC5" define RC5 - -load_on auto - -<add> -rc5.cpp -rc5.h -</add> 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..82931c1d2 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 clear() throw() { S.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/rc6/info.txt index 1457e78c1..2897bc1f3 100644 --- a/src/block/rc6/info.txt +++ b/src/block/rc6/info.txt @@ -1,10 +1,3 @@ realname "RC6" define RC6 - -load_on auto - -<add> -rc6.cpp -rc6.h -</add> 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..6cd0f54db 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 clear() throw() { S.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/safer/info.txt index 973cbff19..7c8067472 100644 --- a/src/block/safer/info.txt +++ b/src/block/safer/info.txt @@ -1,11 +1,3 @@ realname "SAFER" define SAFER - -load_on auto - -<add> -safe_tab.cpp -safer_sk.cpp -safer_sk.h -</add> 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..80d2dc069 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 clear() throw() { EK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/seed/info.txt index d04979335..c66e0c2cd 100644 --- a/src/block/seed/info.txt +++ b/src/block/seed/info.txt @@ -1,11 +1,3 @@ realname "SEED" define SEED - -load_on auto - -<add> -seed.cpp -seed.h -seed_tab.cpp -</add> 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..5a4b44057 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 clear() throw() { K.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/serpent/info.txt index baaccbf01..4031a3f5f 100644 --- a/src/block/serpent/info.txt +++ b/src/block/serpent/info.txt @@ -1,10 +1,3 @@ realname "Serpent" define SERPENT - -load_on auto - -<add> -serpent.cpp -serpent.h -</add> 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..4fa7451b9 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 clear() throw() { round_key.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/serpent_ia32/info.txt index ea0506299..48d589724 100644 --- a/src/block/serpent_ia32/info.txt +++ b/src/block/serpent_ia32/info.txt @@ -4,12 +4,6 @@ define SERPENT_IA32 load_on asm_ok -<add> -serp_ia32_imp.S -serp_ia32.cpp -serp_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_ia32/serp_ia32.cpp index 37dd4e637..721584b18 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; + } } /* @@ -41,7 +51,7 @@ void Serpent_IA32::key_schedule(const byte key[], u32bit length) { SecureBuffer<u32bit, 140> W; for(u32bit j = 0; j != length / 4; ++j) - W[j] = make_u32bit(key[4*j+3], key[4*j+2], key[4*j+1], key[4*j]); + W[j] = load_le<u32bit>(key, j); W[length / 4] |= u32bit(1) << ((length%4)*8); botan_serpent_ia32_key_schedule(W); 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..da7eef6bc --- /dev/null +++ b/src/block/serpent_sse2/info.txt @@ -0,0 +1,8 @@ +realname "Serpent (SSE2)" + +define SERPENT_SSE2 + +<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/info.txt b/src/block/skipjack/info.txt index 4b38d6d28..9cdddfe6b 100644 --- a/src/block/skipjack/info.txt +++ b/src/block/skipjack/info.txt @@ -1,10 +1,3 @@ realname "Skipjack" define SKIPJACK - -load_on auto - -<add> -skipjack.cpp -skipjack.h -</add> diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp index f5ffc861e..e8b2cfb8d 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; + } } /* @@ -153,7 +165,7 @@ void Skipjack::key_schedule(const byte key[], u32bit) /* * Clear memory of sensitive data */ -void Skipjack::clear() throw() +void Skipjack::clear() { for(u32bit j = 0; j != 10; ++j) FTABLE[j].clear(); diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index 231cd9c87..60fad6310 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/info.txt b/src/block/square/info.txt index a20697923..7c517be71 100644 --- a/src/block/square/info.txt +++ b/src/block/square/info.txt @@ -1,11 +1,3 @@ realname "Square" define SQUARE - -load_on auto - -<add> -sqr_tab.cpp -square.cpp -square.h -</add> diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index cb226542d..90f2301cf 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]; } /* @@ -176,7 +196,7 @@ void Square::transform(u32bit round_key[4]) /* * Clear memory of sensitive data */ -void Square::clear() throw() +void Square::clear() { EK.clear(); DK.clear(); diff --git a/src/block/square/square.h b/src/block/square/square.h index 94a1fc370..088122181 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/info.txt b/src/block/tea/info.txt index 6a0e76b15..85a19ee4c 100644 --- a/src/block/tea/info.txt +++ b/src/block/tea/info.txt @@ -1,10 +1,3 @@ realname "TEA" define TEA - -load_on auto - -<add> -tea.cpp -tea.h -</add> 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..c19f272a6 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 clear() throw() { K.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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/info.txt b/src/block/twofish/info.txt index 35639d858..319da6e6e 100644 --- a/src/block/twofish/info.txt +++ b/src/block/twofish/info.txt @@ -1,11 +1,3 @@ realname "Twofish" define TWOFISH - -load_on auto - -<add> -two_tab.cpp -twofish.cpp -twofish.h -</add> diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index 9784b00a2..3136837aa 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; + } } /* @@ -206,7 +218,7 @@ void Twofish::rs_mul(byte S[4], byte key, u32bit offset) /* * Clear memory of sensitive data */ -void Twofish::clear() throw() +void Twofish::clear() { SBox0.clear(); SBox1.clear(); diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 0640e32f8..71a1e8781 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 clear() throw(); + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear(); 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/info.txt b/src/block/xtea/info.txt index 0120a3bce..1887e6673 100644 --- a/src/block/xtea/info.txt +++ b/src/block/xtea/info.txt @@ -1,10 +1,3 @@ realname "XTEA" define XTEA - -load_on auto - -<add> -xtea.cpp -xtea.h -</add> diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index 5047f6594..fc14c0a57 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -7,40 +7,113 @@ #include <botan/xtea.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { +namespace { + +void xtea_encrypt_4(const byte in[32], byte out[32], const u32bit EK[64]) + { + u32bit L0, R0, L1, R1, L2, R2, L3, R3; + load_be(in, L0, R0, L1, R1, L2, R2, L3, R3); + + for(u32bit i = 0; i != 32; ++i) + { + L0 += (((R0 << 4) ^ (R0 >> 5)) + R0) ^ EK[2*i]; + L1 += (((R1 << 4) ^ (R1 >> 5)) + R1) ^ EK[2*i]; + L2 += (((R2 << 4) ^ (R2 >> 5)) + R2) ^ EK[2*i]; + L3 += (((R3 << 4) ^ (R3 >> 5)) + R3) ^ EK[2*i]; + + R0 += (((L0 << 4) ^ (L0 >> 5)) + L0) ^ EK[2*i+1]; + R1 += (((L1 << 4) ^ (L1 >> 5)) + L1) ^ EK[2*i+1]; + R2 += (((L2 << 4) ^ (L2 >> 5)) + L2) ^ EK[2*i+1]; + R3 += (((L3 << 4) ^ (L3 >> 5)) + L3) ^ EK[2*i+1]; + } + + store_be(out, L0, R0, L1, R1, L2, R2, L3, R3); + } + +void xtea_decrypt_4(const byte in[32], byte out[32], const u32bit EK[64]) + { + u32bit L0, R0, L1, R1, L2, R2, L3, R3; + load_be(in, L0, R0, L1, R1, L2, R2, L3, R3); + + for(u32bit i = 0; i != 32; ++i) + { + R0 -= (((L0 << 4) ^ (L0 >> 5)) + L0) ^ EK[63 - 2*i]; + R1 -= (((L1 << 4) ^ (L1 >> 5)) + L1) ^ EK[63 - 2*i]; + R2 -= (((L2 << 4) ^ (L2 >> 5)) + L2) ^ EK[63 - 2*i]; + R3 -= (((L3 << 4) ^ (L3 >> 5)) + L3) ^ EK[63 - 2*i]; + + L0 -= (((R0 << 4) ^ (R0 >> 5)) + R0) ^ EK[62 - 2*i]; + L1 -= (((R1 << 4) ^ (R1 >> 5)) + R1) ^ EK[62 - 2*i]; + L2 -= (((R2 << 4) ^ (R2 >> 5)) + R2) ^ EK[62 - 2*i]; + L3 -= (((R3 << 4) ^ (R3 >> 5)) + R3) ^ EK[62 - 2*i]; + } + + store_be(out, L0, R0, L1, R1, L2, R2, L3, R3); + } + +} + /* * 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) + while(blocks >= 4) { - L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; - R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; + xtea_encrypt_4(in, out, this->EK); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; } - store_be(out, L, R); + for(u32bit i = 0; i != blocks; ++i) + { + 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); + + 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) + while(blocks >= 4) { - R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; - L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; + xtea_decrypt_4(in, out, this->EK); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; } - store_be(out, L, R); + for(u32bit i = 0; i != blocks; ++i) + { + 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); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index d9c6066cb..f3b554edb 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 clear() throw() { EK.clear(); } + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + void clear() { 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.txt b/src/build-data/arch/m68k.txt index 27f246abc..759a3dac1 100644 --- a/src/build-data/arch/m68k.txt +++ b/src/build-data/arch/m68k.txt @@ -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.txt b/src/build-data/arch/ppc.txt index 16112f389..e2dfa6ea2 100644 --- a/src/build-data/arch/ppc.txt +++ b/src/build-data/arch/ppc.txt @@ -1,6 +1,7 @@ realname "PowerPC" endian big +unaligned ok default_submodel ppc604 diff --git a/src/build-data/arch/s390.txt b/src/build-data/arch/s390.txt index 392f51397..312b262c4 100644 --- a/src/build-data/arch/s390.txt +++ b/src/build-data/arch/s390.txt @@ -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.txt b/src/build-data/arch/s390x.txt index 49fb0bda7..9fe6bd615 100644 --- a/src/build-data/arch/s390x.txt +++ b/src/build-data/arch/s390x.txt @@ -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/build-data/cc/bcc.txt b/src/build-data/cc/bcc.txt index df09daff0..fe88c270e 100644 --- a/src/build-data/cc/bcc.txt +++ b/src/build-data/cc/bcc.txt @@ -1,5 +1,7 @@ realname "Borland C++" +macro_name "BORLAND" + binary_name "bcc32" compile_option "-c " diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt new file mode 100644 index 000000000..480794faf --- /dev/null +++ b/src/build-data/cc/clang.txt @@ -0,0 +1,46 @@ +realname "Clang/LLVM" + +# Largely copied from the gcc config + +macro_name "CLANG" + +binary_name clang + +compile_option "-c " +output_to_option "-o " +add_include_dir_option "-I" +add_lib_dir_option "-L" +add_lib_option "-l" + +lang_flags "-D_REENTRANT -ansi -Wno-long-long" +warning_flags "-W -Wall" + +makefile_style unix + +lib_opt_flags "-O2" +check_opt_flags "-O2" +shared_flags "-fPIC" +debug_flags "-g" +no_debug_flags "-finline-functions" + +<so_link_flags> +# The default works for GNU ld and several other Unix linkers +default -> "$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)" +</so_link_flags> + +<mach_abi_linking> +amd64 -> "-m64" +mips64 -> "-mabi=64" +s390 -> "-m31" +s390x -> "-m64" +sparc32 -> "-m32 -mno-app-regs" +sparc64 -> "-m64 -mno-app-regs" +ppc64 -> "-m64" + +# This should probably be used on most/all targets, but the docs are incomplete +openbsd -> "-pthread" +freebsd -> "-pthread" +dragonfly -> "-pthread" +netbsd -> "-pthread -D_NETBSD_SOURCE" +qnx -> "-fexceptions -D_QNX_SOURCE" +</mach_abi_linking> diff --git a/src/build-data/cc/compaq.txt b/src/build-data/cc/compaq.txt index 66d3a5219..94075e888 100644 --- a/src/build-data/cc/compaq.txt +++ b/src/build-data/cc/compaq.txt @@ -1,5 +1,7 @@ realname "Compaq C++" +macro_name "COMPAQ" + binary_name "cxx" compile_option "-c " diff --git a/src/build-data/cc/ekopath.txt b/src/build-data/cc/ekopath.txt index ca2471059..38516e2f3 100644 --- a/src/build-data/cc/ekopath.txt +++ b/src/build-data/cc/ekopath.txt @@ -1,5 +1,7 @@ realname "PathScale EKOPath C++" +macro_name "PATHSCALE" + binary_name "pathCC" compile_option "-c " diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 978ed6d58..9adef8cfb 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -1,5 +1,7 @@ realname "GNU C++" +macro_name "GCC" + binary_name "g++" compiler_has_tr1 yes @@ -14,10 +16,11 @@ lang_flags "-D_REENTRANT -ansi -Wno-long-long" warning_flags "-W -Wall" #warning_flags "-Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" -lib_opt_flags "-O2 -finline-functions" -check_opt_flags "-O2" +lib_opt_flags "-O2" +check_opt_flags "-O" shared_flags "-fPIC" debug_flags "-g" +no_debug_flags "-finline-functions" dll_import_flags "" dll_export_flags "" diff --git a/src/build-data/cc/hpcc.txt b/src/build-data/cc/hpcc.txt index 284e92ca6..9c0d4a784 100644 --- a/src/build-data/cc/hpcc.txt +++ b/src/build-data/cc/hpcc.txt @@ -1,5 +1,7 @@ realname "HP-UX C++" +macro_name "HP_ACC" + binary_name "aCC" compile_option "-c " diff --git a/src/build-data/cc/icc.txt b/src/build-data/cc/icc.txt index 7d8e9682f..9595714f6 100644 --- a/src/build-data/cc/icc.txt +++ b/src/build-data/cc/icc.txt @@ -1,5 +1,7 @@ realname "Intel C++" +macro_name "INTEL" + binary_name "icpc" compiler_has_tr1 yes diff --git a/src/build-data/cc/kai.txt b/src/build-data/cc/kai.txt index 8585e54e0..52ddba4ab 100644 --- a/src/build-data/cc/kai.txt +++ b/src/build-data/cc/kai.txt @@ -1,5 +1,7 @@ realname "KAI C++" +macro_name "KAI" + binary_name "KCC" compile_option "-c " diff --git a/src/build-data/cc/mipspro.txt b/src/build-data/cc/mipspro.txt index b75fc4fb3..a4cfbd1ee 100644 --- a/src/build-data/cc/mipspro.txt +++ b/src/build-data/cc/mipspro.txt @@ -1,5 +1,7 @@ realname "SGI MIPSPro C++" +macro_name "MIPSPRO" + binary_name "CC" compile_option "-c " diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt index 68e4517f8..c19d93e2b 100644 --- a/src/build-data/cc/msvc.txt +++ b/src/build-data/cc/msvc.txt @@ -1,5 +1,7 @@ realname "Visual C++" +macro_name "MSVC" + binary_name "cl.exe" compile_option "/nologo /c " diff --git a/src/build-data/cc/open64.txt b/src/build-data/cc/open64.txt index b7c1e9e99..0157440cf 100644 --- a/src/build-data/cc/open64.txt +++ b/src/build-data/cc/open64.txt @@ -1,5 +1,7 @@ realname "Open64" +macro_name "OPEN64" + binary_name "openCC" compile_option "-c " diff --git a/src/build-data/cc/pgi.txt b/src/build-data/cc/pgi.txt index 35f466477..c4fdb9e70 100644 --- a/src/build-data/cc/pgi.txt +++ b/src/build-data/cc/pgi.txt @@ -1,5 +1,7 @@ realname "Portland Group C++" +macro_name "PORTLAND_GROUP" + binary_name "pgCC" compile_option "-c " diff --git a/src/build-data/cc/sgipro64.txt b/src/build-data/cc/sgipro64.txt index 28132ffcc..be91ac69a 100644 --- a/src/build-data/cc/sgipro64.txt +++ b/src/build-data/cc/sgipro64.txt @@ -1,5 +1,7 @@ realname "SGI Pro64" +macro_name "SGI_PRO64" + binary_name "sgiCC" compile_option "-c " diff --git a/src/build-data/cc/sunwspro.txt b/src/build-data/cc/sunwspro.txt index e1bc0b26f..9756f8538 100644 --- a/src/build-data/cc/sunwspro.txt +++ b/src/build-data/cc/sunwspro.txt @@ -1,5 +1,7 @@ realname "Sun Workshop Pro C++" +macro_name "SUN_WORKSHOP" + binary_name "CC" compile_option "-c " diff --git a/src/build-data/cc/xlc.txt b/src/build-data/cc/xlc.txt index 64b888421..6d06b4c43 100644 --- a/src/build-data/cc/xlc.txt +++ b/src/build-data/cc/xlc.txt @@ -1,5 +1,7 @@ realname "IBM XL C/C++" +macro_name "IBM_XLC" + binary_name "xlC" compile_option "-c " diff --git a/src/build-data/makefile/python.in b/src/build-data/makefile/python.in new file mode 100644 index 000000000..9658c70ce --- /dev/null +++ b/src/build-data/makefile/python.in @@ -0,0 +1,29 @@ +CXX = g++ + +PYTHON_ROOT = /usr/lib/python%{python_version}/config +PYTHON_INC = -I/usr/include/python%{python_version} +PYTHON_SITE_PACKAGE_DIR = /usr/lib/python%{python_version}/site-packages/ + +PYTHON_FLAGS = -Isrc/wrap/python -Os -fPIC -ftemplate-depth-255 -Wall -Wno-unused $(PYTHON_INC) + +PYTHON_OBJS = %{python_objs} + +BOTAN_PYTHON_MODDIR = build/botan-python + +all: $(BOTAN_PYTHON_MODDIR)/_botan.so + +%{python_build_cmds} + +$(BOTAN_PYTHON_MODDIR)/_botan.so: $(PYTHON_OBJS) + rm -rf $(BOTAN_PYTHON_MODDIR) + mkdir $(BOTAN_PYTHON_MODDIR) + cp src/wrap/python/*.py $(BOTAN_PYTHON_MODDIR) + $(CXX) -shared -o $@ $(PYTHON_OBJS) -L. -L$(PYTHON_ROOT) -lbotan -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@ + +clean: + rm -f $(PYTHON_OBJS) $(BOTAN_PYTHON_MODDIR) + +install: + mkdir -p $(PYTHON_SITE_PACKAGE_DIR)/botan + cp $(BOTAN_PYTHON_MODDIR)/* $(PYTHON_SITE_PACKAGE_DIR)/botan + chmod -R u=rwX,go=rX $(PYTHON_SITE_PACKAGE_DIR)/botan diff --git a/src/build-data/makefile/unix.in b/src/build-data/makefile/unix.in index a48a5a17e..8e0e35b87 100644 --- a/src/build-data/makefile/unix.in +++ b/src/build-data/makefile/unix.in @@ -101,7 +101,7 @@ clean: distclean: clean $(RM_R) %{build_dir} $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy - $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG) + $(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG) install: $(LIBRARIES) $(ECHO) "Installing Botan into $(DESTDIR)... " diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in index f718d1160..cfc8e3223 100644 --- a/src/build-data/makefile/unix_shr.in +++ b/src/build-data/makefile/unix_shr.in @@ -115,7 +115,7 @@ clean: distclean: clean $(RM_R) %{build_dir} $(RM_R) %{doc_src_dir}/doxygen %{doc_src_dir}/botan.doxy - $(RM) Makefile $(CONFIG_SCRIPT) $(PKGCONFIG) + $(RM) Makefile* $(CONFIG_SCRIPT) $(PKGCONFIG) install: $(LIBRARIES) $(ECHO) "Installing Botan into $(DESTDIR)... " diff --git a/src/build-data/os/hurd b/src/build-data/os/hurd new file mode 100644 index 000000000..ed56dad75 --- /dev/null +++ b/src/build-data/os/hurd @@ -0,0 +1,16 @@ +realname "Hurd" + +os_type unix + +<target_features> +posix_mlock +</target_features> + +# Is this correct? +<supports_shared> +all +</supports_shared> + +<aliases> +gnu +</aliases> diff --git a/src/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp index 05533b520..947b9e66d 100644 --- a/src/cert/cvc/asn1_eac_tm.cpp +++ b/src/cert/cvc/asn1_eac_tm.cpp @@ -11,53 +11,39 @@ #include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> -#include <ctime> -#include <sstream> +#include <botan/rounding.h> +#include <botan/timer.h> namespace Botan { namespace { -/* -* Convert a time_t to a struct tm -*/ -std::tm get_tm(u64bit timer) - { - std::time_t time_val = static_cast<std::time_t>(timer); - - std::tm* tm_p = std::gmtime(&time_val); - if (tm_p == 0) - throw Encoding_Error("EAC_Time: gmtime could not encode " + - to_string(timer)); - return (*tm_p); - } SecureVector<byte> enc_two_digit(u32bit in) { SecureVector<byte> result; in %= 100; if (in < 10) - { result.append(0x00); - } else { - u32bit y_first_pos = (in - (in%10))/10; + u32bit y_first_pos = round_down(in, 10) / 10; result.append(static_cast<byte>(y_first_pos)); } - u32bit y_sec_pos = in%10; + + u32bit y_sec_pos = in % 10; result.append(static_cast<byte>(y_sec_pos)); return result; } + u32bit dec_two_digit(byte b1, byte b2) { u32bit upper = (u32bit)b1; u32bit lower = (u32bit)b2; - if (upper > 9 || lower > 9) - { - throw Invalid_Argument("u32bit dec_two_digit(byte b1, byte b2): value too large"); - } - return upper*10 + lower; + if(upper > 9 || lower > 9) + throw Invalid_Argument("CVC dec_two_digit value too large"); + + return upper*10 + lower; } } @@ -67,12 +53,11 @@ u32bit dec_two_digit(byte b1, byte b2) EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t) :tag(t) { - std::tm time_info = get_tm(timer); + std::tm time_info = time_t_to_tm(timer); year = time_info.tm_year + 1900; month = time_info.tm_mon + 1; day = time_info.tm_mday; - } /* @@ -272,27 +257,15 @@ bool operator<(const EAC_Time& t1, const EAC_Time& t2) void EAC_Time::decode_from(BER_Decoder& source) { BER_Object obj = source.get_next_object(); - if (obj.type_tag != this->tag) - { - std::string message("decoding type mismatch for EAC_Time, tag is "); - std::stringstream ss; - std::string str_is; - ss << std::hex << obj.type_tag; - ss >> str_is; - message.append(str_is); - message.append(", while it should be "); - std::stringstream ss2; - std::string str_should; - ss2 << std::hex << this->tag; - ss2 >> str_should; - message.append(str_should); - throw Decoding_Error(message); - } - if (obj.value.size() != 6) + if(obj.type_tag != this->tag) + throw BER_Decoding_Error("Tag mismatch when decoding"); + + if(obj.value.size() != 6) { throw Decoding_Error("EAC_Time decoding failed"); } + try { u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]); diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp index 638d3f984..8ca8db0c2 100644 --- a/src/cert/cvc/cvc_ca.cpp +++ b/src/cert/cvc/cvc_ca.cpp @@ -1,7 +1,6 @@ #include <botan/cvc_ca.h> #include <botan/cvc_cert.h> #include <botan/der_enc.h> -#include <botan/util.h> #include <botan/oids.h> namespace Botan { diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 91ea38724..777347a18 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -14,7 +14,7 @@ #include <botan/look_pk.h> #include <botan/cvc_req.h> #include <botan/cvc_ado.h> -#include <botan/util.h> +#include <botan/timer.h> #include <sstream> namespace Botan { diff --git a/src/cert/x509/crl_ent.cpp b/src/cert/x509/crl_ent.cpp index afea8cf6b..a8a989c24 100644 --- a/src/cert/x509/crl_ent.cpp +++ b/src/cert/x509/crl_ent.cpp @@ -11,7 +11,7 @@ #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> namespace Botan { diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 41e314724..f0eb9c3e5 100644 --- a/src/cert/x509/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp @@ -13,7 +13,7 @@ #include <botan/bigint.h> #include <botan/parsing.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> #include <algorithm> #include <typeinfo> #include <iterator> diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp index de9d589a3..03bcd20f4 100644 --- a/src/cert/x509/x509opt.cpp +++ b/src/cert/x509/x509opt.cpp @@ -6,10 +6,9 @@ */ #include <botan/x509self.h> -#include <botan/util.h> -#include <botan/parsing.h> #include <botan/oids.h> -#include <ctime> +#include <botan/parsing.h> +#include <botan/timer.h> namespace Botan { diff --git a/src/cert/x509/x509stor.cpp b/src/cert/x509/x509stor.cpp index cb61bc2d2..40801148c 100644 --- a/src/cert/x509/x509stor.cpp +++ b/src/cert/x509/x509stor.cpp @@ -10,7 +10,7 @@ #include <botan/pubkey.h> #include <botan/look_pk.h> #include <botan/oids.h> -#include <botan/util.h> +#include <botan/timer.h> #include <algorithm> #include <memory> diff --git a/src/checksum/adler32/adler32.h b/src/checksum/adler32/adler32.h index 98a28bc81..79804a842 100644 --- a/src/checksum/adler32/adler32.h +++ b/src/checksum/adler32/adler32.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL Adler32 : public HashFunction { public: - void clear() throw() { S1 = 1; S2 = 0; } + void clear() { S1 = 1; S2 = 0; } std::string name() const { return "Adler32"; } HashFunction* clone() const { return new Adler32; } Adler32() : HashFunction(4) { clear(); } diff --git a/src/checksum/crc24/crc24.h b/src/checksum/crc24/crc24.h index bca4d0e89..f59ac4a45 100644 --- a/src/checksum/crc24/crc24.h +++ b/src/checksum/crc24/crc24.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL CRC24 : public HashFunction { public: - void clear() throw() { crc = 0xB704CE; } + void clear() { crc = 0xB704CE; } std::string name() const { return "CRC24"; } HashFunction* clone() const { return new CRC24; } CRC24() : HashFunction(3) { clear(); } diff --git a/src/checksum/crc32/crc32.h b/src/checksum/crc32/crc32.h index 390fb100e..998e8489e 100644 --- a/src/checksum/crc32/crc32.h +++ b/src/checksum/crc32/crc32.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL CRC32 : public HashFunction { public: - void clear() throw() { crc = 0xFFFFFFFF; } + void clear() { crc = 0xFFFFFFFF; } std::string name() const { return "CRC32"; } HashFunction* clone() const { return new CRC32; } CRC32() : HashFunction(4) { clear(); } diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp index fbacc278b..201c9bfdf 100644 --- a/src/codec/hex/hex.cpp +++ b/src/codec/hex/hex.cpp @@ -13,13 +13,15 @@ namespace Botan { +const u32bit HEX_CODEC_BUFFER_SIZE = 256; + /* * Hex_Encoder Constructor */ Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) : casing(c), line_length(breaks ? length : 0) { - in.create(64); + in.create(HEX_CODEC_BUFFER_SIZE); out.create(2*in.size()); counter = position = 0; } @@ -29,7 +31,7 @@ Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) : */ Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) { - in.create(64); + in.create(HEX_CODEC_BUFFER_SIZE); out.create(2*in.size()); counter = position = 0; } @@ -114,7 +116,7 @@ void Hex_Encoder::end_msg() */ Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) { - in.create(64); + in.create(HEX_CODEC_BUFFER_SIZE); out.create(in.size() / 2); position = 0; } 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/cryptobox/cryptobox.cpp b/src/cryptobox/cryptobox.cpp index c27bbaffa..ba7553c55 100644 --- a/src/cryptobox/cryptobox.cpp +++ b/src/cryptobox/cryptobox.cpp @@ -8,9 +8,8 @@ #include <botan/cryptobox.h> #include <botan/filters.h> #include <botan/pipe.h> -#include <botan/serpent.h> +#include <botan/lookup.h> #include <botan/sha2_64.h> -#include <botan/ctr.h> #include <botan/hmac.h> #include <botan/pbkdf2.h> #include <botan/pem.h> @@ -59,7 +58,7 @@ std::string encrypt(const byte input[], u32bit input_len, InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN, CIPHER_IV_LEN); - Pipe pipe(new CTR_BE(new Serpent, cipher_key, iv), + Pipe pipe(get_cipher("Serpent/CTR-BE", cipher_key, iv, ENCRYPTION), new Fork( 0, new MAC_Filter(new HMAC(new SHA_512), @@ -121,7 +120,7 @@ std::string decrypt(const byte input[], u32bit input_len, CIPHER_IV_LEN); Pipe pipe(new Fork( - new CTR_BE(new Serpent, cipher_key, iv), + get_cipher("Serpent/CTR-BE", cipher_key, iv, ENCRYPTION), new MAC_Filter(new HMAC(new SHA_512), mac_key, MAC_OUTPUT_LEN))); diff --git a/src/engine/def_engine/def_eng.h b/src/engine/def_engine/def_eng.h index 2d7145480..ba5bee8ef 100644 --- a/src/engine/def_engine/def_eng.h +++ b/src/engine/def_engine/def_eng.h @@ -78,6 +78,11 @@ class BOTAN_DLL Default_Engine : public Engine Algorithm_Factory&) const; }; +Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, + Cipher_Dir direction, + const std::string& mode, + const std::string& padding); + } #endif diff --git a/src/engine/def_engine/def_mode.cpp b/src/engine/def_engine/def_mode.cpp index 2b093a0a3..b7373ef84 100644 --- a/src/engine/def_engine/def_mode.cpp +++ b/src/engine/def_engine/def_mode.cpp @@ -32,7 +32,7 @@ #include <botan/ofb.h> #endif -#if defined(BOTAN_HAS_CTR) +#if defined(BOTAN_HAS_CTR_BE) #include <botan/ctr.h> #endif @@ -51,22 +51,22 @@ namespace { /** * Get a block cipher padding method by name */ -BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec, + const std::string& def_if_empty) { - SCAN_Name request(algo_spec); - #if defined(BOTAN_HAS_CIPHER_MODE_PADDING) - if(request.algo_name() == "PKCS7") + if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding")) + return new Null_Padding; + + if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7")) return new PKCS7_Padding; - if(request.algo_name() == "OneAndZeros") + if(algo_spec == "OneAndZeros") return new OneAndZeros_Padding; - if(request.algo_name() == "X9.23") + if(algo_spec == "X9.23") return new ANSI_X923_Padding; - if(request.algo_name() == "NoPadding") - return new Null_Padding; #endif throw Algorithm_Not_Found(algo_spec); @@ -74,85 +74,30 @@ BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) } -/* -* Get a cipher object -*/ -Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, - Cipher_Dir direction, - Algorithm_Factory& af) +Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, + Cipher_Dir direction, + const std::string& mode, + const std::string& padding) { - std::vector<std::string> algo_parts = split_on(algo_spec, '/'); - if(algo_parts.empty()) - throw Invalid_Algorithm_Name(algo_spec); - - const std::string cipher_name = algo_parts[0]; - - // check if it is a stream cipher first (easy case) - const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name); - if(stream_cipher) - return new StreamCipher_Filter(stream_cipher->clone()); - - const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name); - if(!block_cipher) - return 0; - - if(algo_parts.size() != 2 && algo_parts.size() != 3) - return 0; - - std::string mode = algo_parts[1]; - u32bit bits = 0; - - if(mode.find("CFB") != std::string::npos || - mode.find("EAX") != std::string::npos) - { - std::vector<std::string> algo_info = parse_algorithm_name(mode); - mode = algo_info[0]; - if(algo_info.size() == 1) - bits = 8*block_cipher->BLOCK_SIZE; - else if(algo_info.size() == 2) - bits = to_u32bit(algo_info[1]); - else - throw Invalid_Algorithm_Name(algo_spec); - } - - std::string padding; - if(algo_parts.size() == 3) - padding = algo_parts[2]; - else - padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; - - if(mode == "ECB" && padding == "CTS") - return 0; - else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") - throw Invalid_Algorithm_Name(algo_spec); - #if defined(BOTAN_HAS_OFB) if(mode == "OFB") - return new OFB(block_cipher->clone()); + return new StreamCipher_Filter(new OFB(block_cipher->clone())); #endif -#if defined(BOTAN_HAS_CTR) +#if defined(BOTAN_HAS_CTR_BE) if(mode == "CTR-BE") - return new CTR_BE(block_cipher->clone()); + return new StreamCipher_Filter(new CTR_BE(block_cipher->clone())); #endif #if defined(BOTAN_HAS_ECB) - if(mode == "ECB") - { - if(direction == ENCRYPTION) - return new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding)); - else - return new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding)); - } -#endif - -#if defined(BOTAN_HAS_CFB) - if(mode == "CFB") + if(mode == "ECB" || mode == "") { if(direction == ENCRYPTION) - return new CFB_Encryption(block_cipher->clone(), bits); + return new ECB_Encryption(block_cipher->clone(), + get_bc_pad(padding, "NoPadding")); else - return new CFB_Decryption(block_cipher->clone(), bits); + return new ECB_Decryption(block_cipher->clone(), + get_bc_pad(padding, "NoPadding")); } #endif @@ -173,25 +118,15 @@ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, #if defined(BOTAN_HAS_CBC) if(direction == ENCRYPTION) return new CBC_Encryption(block_cipher->clone(), - get_bc_pad(padding)); + get_bc_pad(padding, "PKCS7")); else return new CBC_Decryption(block_cipher->clone(), - get_bc_pad(padding)); + get_bc_pad(padding, "PKCS7")); #else return 0; #endif } -#if defined(BOTAN_HAS_EAX) - if(mode == "EAX") - { - if(direction == ENCRYPTION) - return new EAX_Encryption(block_cipher->clone(), bits); - else - return new EAX_Decryption(block_cipher->clone(), bits); - } -#endif - #if defined(BOTAN_HAS_XTS) if(mode == "XTS") { @@ -202,6 +137,86 @@ Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, } #endif + if(mode.find("CFB") != std::string::npos || + mode.find("EAX") != std::string::npos) + { + u32bit bits = 0; + + std::vector<std::string> algo_info = parse_algorithm_name(mode); + std::string mode_name = algo_info[0]; + if(algo_info.size() == 1) + bits = 8*block_cipher->BLOCK_SIZE; + else if(algo_info.size() == 2) + bits = to_u32bit(algo_info[1]); + else + return 0; + +#if defined(BOTAN_HAS_CFB) + if(mode_name == "CFB") + { + if(direction == ENCRYPTION) + return new CFB_Encryption(block_cipher->clone(), bits); + else + return new CFB_Decryption(block_cipher->clone(), bits); + } +#endif + +#if defined(BOTAN_HAS_EAX) + if(mode_name == "EAX") + { + if(direction == ENCRYPTION) + return new EAX_Encryption(block_cipher->clone(), bits); + else + return new EAX_Decryption(block_cipher->clone(), bits); + } +#endif + } + + return 0; + } + +/* +* Get a cipher object +*/ +Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, + Cipher_Dir direction, + Algorithm_Factory& af) + { + std::vector<std::string> algo_parts = split_on(algo_spec, '/'); + if(algo_parts.empty()) + throw Invalid_Algorithm_Name(algo_spec); + + const std::string cipher_name = algo_parts[0]; + + // check if it is a stream cipher first (easy case) + const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name); + if(stream_cipher) + return new StreamCipher_Filter(stream_cipher->clone()); + + const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name); + if(!block_cipher) + return 0; + + if(algo_parts.size() != 2 && algo_parts.size() != 3) + return 0; + + std::string mode = algo_parts[1]; + + std::string padding; + if(algo_parts.size() == 3) + padding = algo_parts[2]; + else + padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; + + if(mode == "ECB" && padding == "CTS") + return 0; + else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") + throw Invalid_Algorithm_Name(algo_spec); + + Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding); + if(filt) + return filt; + throw Algorithm_Not_Found("get_mode: " + cipher_name + "/" + mode + "/" + padding); } diff --git a/src/engine/def_engine/lookup_hash.cpp b/src/engine/def_engine/lookup_hash.cpp index 58136fc5a..9b2018736 100644 --- a/src/engine/def_engine/lookup_hash.cpp +++ b/src/engine/def_engine/lookup_hash.cpp @@ -22,6 +22,10 @@ #include <botan/crc32.h> #endif +#if defined(BOTAN_HAS_BMW_512) + #include <botan/bmw_512.h> +#endif + #if defined(BOTAN_HAS_FORK_256) #include <botan/fork256.h> #endif @@ -103,6 +107,11 @@ Default_Engine::find_hash(const SCAN_Name& request, return new CRC32; #endif +#if defined(BOTAN_HAS_BMW_512) + if(request.algo_name() == "BMW-512") + return new BMW_512; +#endif + #if defined(BOTAN_HAS_FORK_256) if(request.algo_name() == "FORK-256") return new FORK_256; diff --git a/src/engine/openssl/arc4_openssl.cpp b/src/engine/openssl/arc4_openssl.cpp index 08ed3eb10..793e1faff 100644 --- a/src/engine/openssl/arc4_openssl.cpp +++ b/src/engine/openssl/arc4_openssl.cpp @@ -19,7 +19,7 @@ namespace { class ARC4_OpenSSL : public StreamCipher { public: - void clear() throw() { std::memset(&state, 0, sizeof(state)); } + void clear() { std::memset(&state, 0, sizeof(state)); } std::string name() const; StreamCipher* clone() const { return new ARC4_OpenSSL(SKIP); } diff --git a/src/engine/openssl/ossl_bc.cpp b/src/engine/openssl/ossl_bc.cpp index 4d3761adb..7fdf54e42 100644 --- a/src/engine/openssl/ossl_bc.cpp +++ b/src/engine/openssl/ossl_bc.cpp @@ -18,7 +18,7 @@ namespace { class EVP_BlockCipher : public BlockCipher { public: - void clear() throw(); + void clear(); std::string name() const { return cipher_name; } BlockCipher* clone() const; EVP_BlockCipher(const EVP_CIPHER*, const std::string&); @@ -27,8 +27,8 @@ class EVP_BlockCipher : public BlockCipher ~EVP_BlockCipher(); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; void key_schedule(const byte[], u32bit); std::string cipher_name; mutable EVP_CIPHER_CTX encrypt, decrypt; @@ -90,19 +90,21 @@ EVP_BlockCipher::~EVP_BlockCipher() /* * Encrypt a block */ -void EVP_BlockCipher::enc(const byte in[], byte out[]) const +void EVP_BlockCipher::encrypt_n(const byte in[], byte out[], + u32bit blocks) const { int out_len = 0; - EVP_EncryptUpdate(&encrypt, out, &out_len, in, BLOCK_SIZE); + EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * BLOCK_SIZE); } /* * Decrypt a block */ -void EVP_BlockCipher::dec(const byte in[], byte out[]) const +void EVP_BlockCipher::decrypt_n(const byte in[], byte out[], + u32bit blocks) const { int out_len = 0; - EVP_DecryptUpdate(&decrypt, out, &out_len, in, BLOCK_SIZE); + EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * BLOCK_SIZE); } /* @@ -143,7 +145,7 @@ BlockCipher* EVP_BlockCipher::clone() const /* * Clear memory of sensitive data */ -void EVP_BlockCipher::clear() throw() +void EVP_BlockCipher::clear() { const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt); @@ -174,7 +176,7 @@ OpenSSL_Engine::find_block_cipher(const SCAN_Name& request, if(request.algo_name() == NAME && request.arg_count() == 0) \ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD); -#if 0 +#if !defined(OPENSSL_NO_AES) /* Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g cause is unknown @@ -184,12 +186,36 @@ OpenSSL_Engine::find_block_cipher(const SCAN_Name& request, HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb()); #endif +#if !defined(OPENSSL_NO_DES) HANDLE_EVP_CIPHER("DES", EVP_des_ecb()); HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8); +#endif +#if !defined(OPENSSL_NO_BF) HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1); +#endif + +#if !defined(OPENSSL_NO_CAST) HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1); +#endif + +#if !defined(OPENSSL_NO_RC2) HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1); +#endif + +#if !defined(OPENSSL_NO_RC5) + if(request.algo_name() == "RC5") + if(request.arg_as_u32bit(0, 12) == 12) + return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb(), "RC5(12)", 1, 32, 1); +#endif + +#if !defined(OPENSSL_NO_IDEA) + HANDLE_EVP_CIPHER("IDEA", EVP_idea_ecb()); +#endif + +#if !defined(OPENSSL_NO_SEED) + HANDLE_EVP_CIPHER("SEED", EVP_seed_ecb()); +#endif #undef HANDLE_EVP_CIPHER #undef HANDLE_EVP_CIPHER_KEYLEN diff --git a/src/engine/openssl/ossl_md.cpp b/src/engine/openssl/ossl_md.cpp index 7c8fb678c..1e01a6f25 100644 --- a/src/engine/openssl/ossl_md.cpp +++ b/src/engine/openssl/ossl_md.cpp @@ -18,7 +18,7 @@ namespace { class EVP_HashFunction : public HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return algo_name; } HashFunction* clone() const; EVP_HashFunction(const EVP_MD*, const std::string&); @@ -52,7 +52,7 @@ void EVP_HashFunction::final_result(byte output[]) /* * Clear memory of sensitive data */ -void EVP_HashFunction::clear() throw() +void EVP_HashFunction::clear() { const EVP_MD* algo = EVP_MD_CTX_md(&md); EVP_DigestInit_ex(&md, algo, 0); @@ -95,27 +95,41 @@ EVP_HashFunction::~EVP_HashFunction() HashFunction* OpenSSL_Engine::find_hash(const SCAN_Name& request, Algorithm_Factory&) const { -#ifndef OPENSSL_NO_SHA +#if !defined(OPENSSL_NO_SHA) if(request.algo_name() == "SHA-160") return new EVP_HashFunction(EVP_sha1(), "SHA-160"); #endif -#ifndef OPENSSL_NO_MD2 +#if !defined(OPENSSL_NO_SHA256) + if(request.algo_name() == "SHA-224") + return new EVP_HashFunction(EVP_sha224(), "SHA-224"); + if(request.algo_name() == "SHA-256") + return new EVP_HashFunction(EVP_sha256(), "SHA-256"); +#endif + +#if !defined(OPENSSL_NO_SHA512) + if(request.algo_name() == "SHA-384") + return new EVP_HashFunction(EVP_sha384(), "SHA-384"); + if(request.algo_name() == "SHA-512") + return new EVP_HashFunction(EVP_sha512(), "SHA-512"); +#endif + +#if !defined(OPENSSL_NO_MD2) if(request.algo_name() == "MD2") return new EVP_HashFunction(EVP_md2(), "MD2"); #endif -#ifndef OPENSSL_NO_MD4 +#if !defined(OPENSSL_NO_MD4) if(request.algo_name() == "MD4") return new EVP_HashFunction(EVP_md4(), "MD4"); #endif -#ifndef OPENSSL_NO_MD5 +#if !defined(OPENSSL_NO_MD5) if(request.algo_name() == "MD5") return new EVP_HashFunction(EVP_md5(), "MD5"); #endif -#ifndef OPENSSL_NO_RIPEMD +#if !defined(OPENSSL_NO_RIPEMD) if(request.algo_name() == "RIPEMD-160") return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160"); #endif diff --git a/src/engine/sse2_eng/eng_sse2.cpp b/src/engine/sse2_eng/eng_sse2.cpp index c738b3d96..07c625c7c 100644 --- a/src/engine/sse2_eng/eng_sse2.cpp +++ b/src/engine/sse2_eng/eng_sse2.cpp @@ -1,21 +1,45 @@ /** * SSE2 Assembly Engine -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/eng_sse2.h> +#include <botan/cpuid.h> #if defined(BOTAN_HAS_SHA1_SSE2) #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(!CPUID::has_sse2()) + return 0; + +#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(!CPUID::has_sse2()) + return 0; + #if defined(BOTAN_HAS_SHA1_SSE2) if(request.algo_name() == "SHA-160") return new SHA_160_SSE2; 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/entropy/dev_random/info.txt b/src/entropy/dev_random/info.txt index fddb7ac06..5231b2901 100644 --- a/src/entropy/dev_random/info.txt +++ b/src/entropy/dev_random/info.txt @@ -18,6 +18,7 @@ darwin freebsd dragonfly hpux +hurd irix linux netbsd diff --git a/src/entropy/proc_walk/info.txt b/src/entropy/proc_walk/info.txt index db96ccdb8..b82929a73 100644 --- a/src/entropy/proc_walk/info.txt +++ b/src/entropy/proc_walk/info.txt @@ -17,6 +17,7 @@ darwin freebsd dragonfly hpux +hurd irix linux openbsd diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp index 23f7a20cf..51bf92380 100644 --- a/src/filters/algo_filt.cpp +++ b/src/filters/algo_filt.cpp @@ -14,20 +14,31 @@ namespace Botan { /* * StreamCipher_Filter Constructor */ -StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : +StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) : buffer(DEFAULT_BUFFERSIZE) { - Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = cipher = af.make_stream_cipher(sc_name); + cipher = stream_cipher; } /* * StreamCipher_Filter Constructor */ -StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) : +StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher, + const SymmetricKey& key) : buffer(DEFAULT_BUFFERSIZE) { - base_ptr = cipher = stream_cipher; + cipher = stream_cipher; + cipher->set_key(key); + } + +/* +* StreamCipher_Filter Constructor +*/ +StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : + buffer(DEFAULT_BUFFERSIZE) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + cipher = af.make_stream_cipher(sc_name); } /* @@ -38,7 +49,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); } @@ -47,7 +58,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name, */ void StreamCipher_Filter::set_iv(const InitializationVector& iv) { - cipher->resync(iv.begin(), iv.length()); + cipher->set_iv(iv.begin(), iv.length()); } /* @@ -58,7 +69,7 @@ void StreamCipher_Filter::write(const byte input[], u32bit length) while(length) { u32bit copied = std::min(length, buffer.size()); - cipher->encrypt(input, buffer, copied); + cipher->cipher(input, buffer, copied); send(buffer, copied); input += copied; length -= copied; @@ -95,7 +106,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 +116,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..b1bcb1a00 100644 --- a/src/filters/basefilt.h +++ b/src/filters/basefilt.h @@ -9,11 +9,18 @@ #define BOTAN_BASEFILT_H__ #include <botan/filter.h> -#include <botan/sym_algo.h> namespace Botan { /** +* BitBucket is a filter which simply discards all inputs +*/ +struct BitBucket : public Filter + { + void write(const byte[], u32bit) {} + }; + +/** * This class represents Filter chains. A Filter chain is an ordered * concatenation of Filters, the input to a Chain sequentially passes * through all the Filters contained in the Chain. @@ -62,38 +69,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..208332a56 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,24 +38,34 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter public: /** - * Seek in the stream. - * @param position the position to seek ahead + * Write input data + * @param input data + * @param input_len length of input in bytes */ - void seek(u32bit position) { cipher->seek(position); } + void write(const byte input[], u32bit input_len); - /** - * Find out whether the cipher underlying this filter supports - * resyncing. - * @return true if the cipher supports resyncing - */ - bool supports_resync() const { return (cipher->IV_LENGTH != 0); } + bool valid_iv_length(u32bit iv_len) + { return cipher->valid_iv_length(iv_len); } /** * Set the initialization vector for this 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. @@ -63,6 +75,13 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter /** * Construct a stream cipher filter. + * @param cipher_obj a cipher object to use + * @param key the key to use inside this filter + */ + StreamCipher_Filter(StreamCipher* cipher_obj, const SymmetricKey& key); + + /** + * Construct a stream cipher filter. * @param cipher the name of the desired cipher */ StreamCipher_Filter(const std::string& cipher); @@ -126,6 +145,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 +169,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 +185,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/bmw/bmw_512.cpp b/src/hash/bmw/bmw_512.cpp new file mode 100644 index 000000000..ae80d5725 --- /dev/null +++ b/src/hash/bmw/bmw_512.cpp @@ -0,0 +1,203 @@ +/* +* Blue Midnight Wish 512 (Round 2 tweaked) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/bmw_512.h> +#include <botan/loadstor.h> +#include <botan/rotate.h> + +namespace Botan { + +namespace { + +inline u64bit S0(u64bit X) + { + return (X >> 1) ^ (X << 3) ^ rotate_left(X, 4) ^ rotate_left(X, 37); + } + +inline u64bit S1(u64bit X) + { + return (X >> 1) ^ (X << 2) ^ rotate_left(X, 13) ^ rotate_left(X, 43); + } + +inline u64bit S2(u64bit X) + { + return (X >> 2) ^ (X << 1) ^ rotate_left(X, 19) ^ rotate_left(X, 53); + } + +inline u64bit S3(u64bit X) + { + return (X >> 2) ^ (X << 2) ^ rotate_left(X, 28) ^ rotate_left(X, 59); + } + +inline u64bit S4(u64bit X) + { + return (X >> 1) ^ X; + } + +/** +* Blue Midnight Wish 512 compression function +*/ +void BMW_512_compress(u64bit H[16], const u64bit M[16], u64bit Q[32]) + { + const u32bit EXPAND_1_ROUNDS = 2; + + for(u32bit i = 0; i != 16; ++i) + Q[i] = H[i] ^ M[i]; + + Q[16] = Q[ 5] - Q[ 7] + Q[10] + Q[13] + Q[14]; + Q[17] = Q[ 6] - Q[ 8] + Q[11] + Q[14] - Q[15]; + Q[18] = Q[ 0] + Q[ 7] + Q[ 9] - Q[12] + Q[15]; + Q[19] = Q[ 0] - Q[ 1] + Q[ 8] - Q[10] + Q[13]; + Q[20] = Q[ 1] + Q[ 2] + Q[ 9] - Q[11] - Q[14]; + Q[21] = Q[ 3] - Q[ 2] + Q[10] - Q[12] + Q[15]; + Q[22] = Q[ 4] - Q[ 0] - Q[ 3] - Q[11] + Q[13]; + Q[23] = Q[ 1] - Q[ 4] - Q[ 5] - Q[12] - Q[14]; + Q[24] = Q[ 2] - Q[ 5] - Q[ 6] + Q[13] - Q[15]; + Q[25] = Q[ 0] - Q[ 3] + Q[ 6] - Q[ 7] + Q[14]; + Q[26] = Q[ 8] - Q[ 1] - Q[ 4] - Q[ 7] + Q[15]; + Q[27] = Q[ 8] - Q[ 0] - Q[ 2] - Q[ 5] + Q[ 9]; + Q[28] = Q[ 1] + Q[ 3] - Q[ 6] - Q[ 9] + Q[10]; + Q[29] = Q[ 2] + Q[ 4] + Q[ 7] + Q[10] + Q[11]; + Q[30] = Q[ 3] - Q[ 5] + Q[ 8] - Q[11] - Q[12]; + Q[31] = Q[12] - Q[ 4] - Q[ 6] - Q[ 9] + Q[13]; + + Q[ 0] = S0(Q[16]) + H[ 1]; + Q[ 1] = S1(Q[17]) + H[ 2]; + Q[ 2] = S2(Q[18]) + H[ 3]; + Q[ 3] = S3(Q[19]) + H[ 4]; + Q[ 4] = S4(Q[20]) + H[ 5]; + Q[ 5] = S0(Q[21]) + H[ 6]; + Q[ 6] = S1(Q[22]) + H[ 7]; + Q[ 7] = S2(Q[23]) + H[ 8]; + Q[ 8] = S3(Q[24]) + H[ 9]; + Q[ 9] = S4(Q[25]) + H[10]; + Q[10] = S0(Q[26]) + H[11]; + Q[11] = S1(Q[27]) + H[12]; + Q[12] = S2(Q[28]) + H[13]; + Q[13] = S3(Q[29]) + H[14]; + Q[14] = S4(Q[30]) + H[15]; + Q[15] = S0(Q[31]) + H[ 0]; + + for(u32bit i = 16; i != 16 + EXPAND_1_ROUNDS; ++i) + { + Q[i] = S1(Q[i-16]) + S2(Q[i-15]) + S3(Q[i-14]) + S0(Q[i-13]) + + S1(Q[i-12]) + S2(Q[i-11]) + S3(Q[i-10]) + S0(Q[i- 9]) + + S1(Q[i- 8]) + S2(Q[i- 7]) + S3(Q[i- 6]) + S0(Q[i- 5]) + + S1(Q[i- 4]) + S2(Q[i- 3]) + S3(Q[i- 2]) + S0(Q[i- 1]) + + ((rotate_left(M[(i-16) % 16], ((i-16)%16) + 1) + + rotate_left(M[(i-13) % 16], ((i-13)%16) + 1) - + rotate_left(M[(i- 6) % 16], ((i-6)%16) + 1) + + (0x0555555555555555 * i)) ^ H[(i-16+7)%16]); + } + + for(u32bit i = 16 + EXPAND_1_ROUNDS; i != 32; ++i) + { + Q[i] = Q[i-16] + rotate_left(Q[i-15], 5) + + Q[i-14] + rotate_left(Q[i-13], 11) + + Q[i-12] + rotate_left(Q[i-11], 27) + + Q[i-10] + rotate_left(Q[i- 9], 32) + + Q[i- 8] + rotate_left(Q[i- 7], 37) + + Q[i- 6] + rotate_left(Q[i- 5], 43) + + Q[i- 4] + rotate_left(Q[i- 3], 53) + + S4(Q[i - 2]) + ((Q[i-1] >> 2) ^ Q[i-1]) + + ((rotate_left(M[(i-16) % 16], ((i-16)%16 + 1)) + + rotate_left(M[(i-13) % 16], ((i-13)%16 + 1)) - + rotate_left(M[(i- 6) % 16], ((i-6)%16 + 1)) + + (0x0555555555555555 * i)) ^ H[(i-16+7)%16]); + } + + u64bit XL = Q[16] ^ Q[17] ^ Q[18] ^ Q[19] ^ + Q[20] ^ Q[21] ^ Q[22] ^ Q[23]; + + u64bit XH = Q[24] ^ Q[25] ^ Q[26] ^ Q[27] ^ + Q[28] ^ Q[29] ^ Q[30] ^ Q[31]; + + XH ^= XL; + + H[ 0] = ((XH << 5) ^ (Q[16] >> 5) ^ M[0]) + (XL ^ Q[24] ^ Q[0]); + H[ 1] = ((XH >> 7) ^ (Q[17] << 8) ^ M[1]) + (XL ^ Q[25] ^ Q[1]); + H[ 2] = ((XH >> 5) ^ (Q[18] << 5) ^ M[2]) + (XL ^ Q[26] ^ Q[2]); + H[ 3] = ((XH >> 1) ^ (Q[19] << 5) ^ M[3]) + (XL ^ Q[27] ^ Q[3]); + H[ 4] = ((XH >> 3) ^ (Q[20] ) ^ M[4]) + (XL ^ Q[28] ^ Q[4]); + H[ 5] = ((XH << 6) ^ (Q[21] >> 6) ^ M[5]) + (XL ^ Q[29] ^ Q[5]); + H[ 6] = ((XH >> 4) ^ (Q[22] << 6) ^ M[6]) + (XL ^ Q[30] ^ Q[6]); + H[ 7] = ((XH >> 11) ^ (Q[23] << 2) ^ M[7]) + (XL ^ Q[31] ^ Q[7]); + + H[ 8] = rotate_left(H[4], 9) + (XH ^ Q[24] ^ M[ 8]) + ((XL << 8) ^ Q[23] ^ Q[ 8]); + H[ 9] = rotate_left(H[5], 10) + (XH ^ Q[25] ^ M[ 9]) + ((XL >> 6) ^ Q[16] ^ Q[ 9]); + H[10] = rotate_left(H[6], 11) + (XH ^ Q[26] ^ M[10]) + ((XL << 6) ^ Q[17] ^ Q[10]); + H[11] = rotate_left(H[7], 12) + (XH ^ Q[27] ^ M[11]) + ((XL << 4) ^ Q[18] ^ Q[11]); + H[12] = rotate_left(H[0], 13) + (XH ^ Q[28] ^ M[12]) + ((XL >> 3) ^ Q[19] ^ Q[12]); + H[13] = rotate_left(H[1], 14) + (XH ^ Q[29] ^ M[13]) + ((XL >> 4) ^ Q[20] ^ Q[13]); + H[14] = rotate_left(H[2], 15) + (XH ^ Q[30] ^ M[14]) + ((XL >> 7) ^ Q[21] ^ Q[14]); + H[15] = rotate_left(H[3], 16) + (XH ^ Q[31] ^ M[15]) + ((XL >> 2) ^ Q[22] ^ Q[15]); + } + +} + +void BMW_512::compress_n(const byte input[], u32bit blocks) + { + for(u32bit i = 0; i != blocks; ++i) + { + for(u32bit j = 0; j != 16; ++j) + M[j] = load_le<u64bit>(input, j); + + BMW_512_compress(H, M, Q); + + input += HASH_BLOCK_SIZE; + } + } + +/* +* Copy out the digest +*/ +void BMW_512::copy_out(byte output[]) + { + u64bit final[16] = { + 0xAAAAAAAAAAAAAAA0, 0xAAAAAAAAAAAAAAA1, + 0xAAAAAAAAAAAAAAA2, 0xAAAAAAAAAAAAAAA3, + 0xAAAAAAAAAAAAAAA4, 0xAAAAAAAAAAAAAAA5, + 0xAAAAAAAAAAAAAAA6, 0xAAAAAAAAAAAAAAA7, + 0xAAAAAAAAAAAAAAA8, 0xAAAAAAAAAAAAAAA9, + 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAB, + 0xAAAAAAAAAAAAAAAC, 0xAAAAAAAAAAAAAAAD, + 0xAAAAAAAAAAAAAAAE, 0xAAAAAAAAAAAAAAAF }; + + BMW_512_compress(final, H, Q); + + for(u32bit i = 0; i != OUTPUT_LENGTH; i += 8) + store_le(final[8 + i/8], output + i); + } + +/* +* Clear memory of sensitive data +*/ +void BMW_512::clear() + { + MDx_HashFunction::clear(); + M.clear(); + Q.clear(); + + H[ 0] = 0x8081828384858687; + H[ 1] = 0x88898A8B8C8D8E8F; + H[ 2] = 0x9091929394959697; + H[ 3] = 0x98999A9B9C9D9E9F; + H[ 4] = 0xA0A1A2A3A4A5A6A7; + H[ 5] = 0xA8A9AAABACADAEAF; + H[ 6] = 0xB0B1B2B3B4B5B6B7; + H[ 7] = 0xB8B9BABBBCBDBEBF; + H[ 8] = 0xC0C1C2C3C4C5C6C7; + H[ 9] = 0xC8C9CACBCCCDCECF; + H[10] = 0xD0D1D2D3D4D5D6D7; + H[11] = 0xD8D9DADBDCDDDEDF; + H[12] = 0xE0E1E2E3E4E5E6E7; + H[13] = 0xE8E9EAEBECEDEEEF; + H[14] = 0xF0F1F2F3F4F5F6F7; + H[15] = 0xF8F9FAFBFCFDFEFF; + } + +} diff --git a/src/hash/bmw/bmw_512.h b/src/hash/bmw/bmw_512.h new file mode 100644 index 000000000..55cd761a9 --- /dev/null +++ b/src/hash/bmw/bmw_512.h @@ -0,0 +1,32 @@ +/* +* Blue Midnight Wish 512 (Round 2 tweaked) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BMW_512_H__ +#define BOTAN_BMW_512_H__ + +#include <botan/mdx_hash.h> + +namespace Botan { + +class BMW_512 : public MDx_HashFunction + { + public: + void clear(); + std::string name() const { return "BMW512"; } + HashFunction* clone() const { return new BMW_512; } + BMW_512() : MDx_HashFunction(64, 128, false, true) { clear(); } + private: + void compress_n(const byte input[], u32bit blocks); + void copy_out(byte output[]); + + SecureBuffer<u64bit, 16> H, M; + SecureBuffer<u64bit, 32> Q; + }; + +} + +#endif diff --git a/src/hash/bmw/info.txt b/src/hash/bmw/info.txt new file mode 100644 index 000000000..27e069c0a --- /dev/null +++ b/src/hash/bmw/info.txt @@ -0,0 +1,7 @@ +realname "Blue Midnight Wish" + +define BMW_512 + +<requires> +mdx_hash +</requires> diff --git a/src/hash/fork256/fork256.cpp b/src/hash/fork256/fork256.cpp index f80bff43a..6718f9f97 100644 --- a/src/hash/fork256/fork256.cpp +++ b/src/hash/fork256/fork256.cpp @@ -133,7 +133,7 @@ void FORK_256::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void FORK_256::clear() throw() +void FORK_256::clear() { MDx_HashFunction::clear(); digest[0] = 0x6A09E667; diff --git a/src/hash/fork256/fork256.h b/src/hash/fork256/fork256.h index 70d336cc9..f535370e6 100644 --- a/src/hash/fork256/fork256.h +++ b/src/hash/fork256/fork256.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL FORK_256 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "FORK-256"; } HashFunction* clone() const { return new FORK_256; } FORK_256() : MDx_HashFunction(32, 64, true, true) { clear(); } diff --git a/src/hash/fork256/info.txt b/src/hash/fork256/info.txt index ae0c9f1a4..7c3c5bb94 100644 --- a/src/hash/fork256/info.txt +++ b/src/hash/fork256/info.txt @@ -2,13 +2,6 @@ realname "FORK-256" define FORK_256 -load_on auto - -<add> -fork256.cpp -fork256.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index 3c7f5f92b..90ef3e805 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -1,6 +1,8 @@ /* * GOST 34.11 * (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #include <botan/gost_3411.h> @@ -21,7 +23,7 @@ GOST_34_11::GOST_34_11() : position = 0; } -void GOST_34_11::clear() throw() +void GOST_34_11::clear() { cipher.clear(); sum.clear(); diff --git a/src/hash/gost_3411/gost_3411.h b/src/hash/gost_3411/gost_3411.h index c69555052..7b17bdc1f 100644 --- a/src/hash/gost_3411/gost_3411.h +++ b/src/hash/gost_3411/gost_3411.h @@ -1,6 +1,8 @@ /** * GOST 34.11 * (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license */ #ifndef BOTAN_GOST_3411_H__ @@ -17,7 +19,7 @@ namespace Botan { class BOTAN_DLL GOST_34_11 : public HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "GOST-R-34.11-94" ; } HashFunction* clone() const { return new GOST_34_11; } diff --git a/src/hash/gost_3411/info.txt b/src/hash/gost_3411/info.txt index 65b9475e1..353ceb3e5 100644 --- a/src/hash/gost_3411/info.txt +++ b/src/hash/gost_3411/info.txt @@ -2,13 +2,6 @@ realname "GOST 34.11" define GOST_34_11 -load_on auto - -<add> -gost_3411.cpp -gost_3411.h -</add> - <requires> gost_28147 </requires> diff --git a/src/hash/has160/has160.cpp b/src/hash/has160/has160.cpp index 9a505d31d..533efe595 100644 --- a/src/hash/has160/has160.cpp +++ b/src/hash/has160/has160.cpp @@ -145,7 +145,7 @@ void HAS_160::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void HAS_160::clear() throw() +void HAS_160::clear() { MDx_HashFunction::clear(); X.clear(); diff --git a/src/hash/has160/has160.h b/src/hash/has160/has160.h index 44bb63b9d..cae66c93a 100644 --- a/src/hash/has160/has160.h +++ b/src/hash/has160/has160.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL HAS_160 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "HAS-160"; } HashFunction* clone() const { return new HAS_160; } HAS_160() : MDx_HashFunction(20, 64, false, true) { clear(); } diff --git a/src/hash/has160/info.txt b/src/hash/has160/info.txt index a945f3225..98cbc5155 100644 --- a/src/hash/has160/info.txt +++ b/src/hash/has160/info.txt @@ -2,13 +2,6 @@ realname "HAS-160" define HAS_160 -load_on auto - -<add> -has160.cpp -has160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/hash.h b/src/hash/hash.h index a30234be0..1098951d8 100644 --- a/src/hash/hash.h +++ b/src/hash/hash.h @@ -38,7 +38,7 @@ class BOTAN_DLL HashFunction : public BufferedComputation /** * Reset the internal state of this object. */ - virtual void clear() throw() = 0; + virtual void clear() = 0; HashFunction(u32bit hash_len, u32bit block_len = 0) : BufferedComputation(hash_len), HASH_BLOCK_SIZE(block_len) {} diff --git a/src/hash/md2/info.txt b/src/hash/md2/info.txt index ff33e1eb3..4428584fd 100644 --- a/src/hash/md2/info.txt +++ b/src/hash/md2/info.txt @@ -1,10 +1,3 @@ realname "MD2" define MD2 - -load_on auto - -<add> -md2.cpp -md2.h -</add> diff --git a/src/hash/md2/md2.cpp b/src/hash/md2/md2.cpp index c67e72b5a..f03518ec0 100644 --- a/src/hash/md2/md2.cpp +++ b/src/hash/md2/md2.cpp @@ -97,7 +97,7 @@ void MD2::final_result(byte output[]) /** * Clear memory of sensitive data */ -void MD2::clear() throw() +void MD2::clear() { X.clear(); checksum.clear(); diff --git a/src/hash/md2/md2.h b/src/hash/md2/md2.h index 9337c43f4..0a7125759 100644 --- a/src/hash/md2/md2.h +++ b/src/hash/md2/md2.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL MD2 : public HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "MD2"; } HashFunction* clone() const { return new MD2; } MD2() : HashFunction(16, 16) { clear(); } diff --git a/src/hash/md4/info.txt b/src/hash/md4/info.txt index fc9cbe116..6aa4a5d59 100644 --- a/src/hash/md4/info.txt +++ b/src/hash/md4/info.txt @@ -2,13 +2,6 @@ realname "MD4" define MD4 -load_on auto - -<add> -md4.cpp -md4.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/md4/md4.cpp b/src/hash/md4/md4.cpp index 39e3c8c41..b2870066d 100644 --- a/src/hash/md4/md4.cpp +++ b/src/hash/md4/md4.cpp @@ -95,7 +95,7 @@ void MD4::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void MD4::clear() throw() +void MD4::clear() { MDx_HashFunction::clear(); M.clear(); diff --git a/src/hash/md4/md4.h b/src/hash/md4/md4.h index df6f2292d..0b76a70e4 100644 --- a/src/hash/md4/md4.h +++ b/src/hash/md4/md4.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL MD4 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "MD4"; } HashFunction* clone() const { return new MD4; } MD4() : MDx_HashFunction(16, 64, false, true) { clear(); } diff --git a/src/hash/md4_ia32/info.txt b/src/hash/md4_ia32/info.txt index fee7dd1a8..217c3fc21 100644 --- a/src/hash/md4_ia32/info.txt +++ b/src/hash/md4_ia32/info.txt @@ -4,12 +4,6 @@ define MD4_IA32 load_on asm_ok -<add> -md4_ia32_imp.S -md4_ia32.cpp -md4_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/md5/info.txt b/src/hash/md5/info.txt index 525a45ab5..14861d635 100644 --- a/src/hash/md5/info.txt +++ b/src/hash/md5/info.txt @@ -2,13 +2,6 @@ realname "MD5" define MD5 -load_on auto - -<add> -md5.cpp -md5.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/md5/md5.cpp b/src/hash/md5/md5.cpp index 7c280aab7..163413bec 100644 --- a/src/hash/md5/md5.cpp +++ b/src/hash/md5/md5.cpp @@ -123,7 +123,7 @@ void MD5::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void MD5::clear() throw() +void MD5::clear() { MDx_HashFunction::clear(); M.clear(); diff --git a/src/hash/md5/md5.h b/src/hash/md5/md5.h index 85f684d8b..456a02c28 100644 --- a/src/hash/md5/md5.h +++ b/src/hash/md5/md5.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL MD5 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "MD5"; } HashFunction* clone() const { return new MD5; } MD5() : MDx_HashFunction(16, 64, false, true) { clear(); } diff --git a/src/hash/md5_ia32/info.txt b/src/hash/md5_ia32/info.txt index ad9923b26..d298f2005 100644 --- a/src/hash/md5_ia32/info.txt +++ b/src/hash/md5_ia32/info.txt @@ -4,12 +4,6 @@ define MD5_IA32 load_on asm_ok -<add> -md5_ia32_imp.S -md5_ia32.cpp -md5_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/mdx_hash/info.txt b/src/hash/mdx_hash/info.txt index 412c93350..ee4ccd6da 100644 --- a/src/hash/mdx_hash/info.txt +++ b/src/hash/mdx_hash/info.txt @@ -3,8 +3,3 @@ realname "MDx Hash Base" define MDX_HASH_FUNCTION load_on dep - -<add> -mdx_hash.cpp -mdx_hash.h -</add> diff --git a/src/hash/mdx_hash/mdx_hash.cpp b/src/hash/mdx_hash/mdx_hash.cpp index b630ec227..28402c2c5 100644 --- a/src/hash/mdx_hash/mdx_hash.cpp +++ b/src/hash/mdx_hash/mdx_hash.cpp @@ -28,7 +28,7 @@ MDx_HashFunction::MDx_HashFunction(u32bit hash_len, u32bit block_len, /** * Clear memory of sensitive data */ -void MDx_HashFunction::clear() throw() +void MDx_HashFunction::clear() { buffer.clear(); count = position = 0; diff --git a/src/hash/mdx_hash/mdx_hash.h b/src/hash/mdx_hash/mdx_hash.h index 0c3aa7806..2d70deed3 100644 --- a/src/hash/mdx_hash/mdx_hash.h +++ b/src/hash/mdx_hash/mdx_hash.h @@ -25,7 +25,7 @@ class BOTAN_DLL MDx_HashFunction : public HashFunction void final_result(byte output[]); virtual void compress_n(const byte block[], u32bit block_n) = 0; - void clear() throw(); + void clear(); virtual void copy_out(byte[]) = 0; virtual void write_count(byte[]); private: diff --git a/src/hash/par_hash/info.txt b/src/hash/par_hash/info.txt index 45716aac8..029939cb5 100644 --- a/src/hash/par_hash/info.txt +++ b/src/hash/par_hash/info.txt @@ -1,10 +1,3 @@ realname "Parallel Hash" define PARALLEL_HASH - -load_on auto - -<add> -par_hash.cpp -par_hash.h -</add> diff --git a/src/hash/par_hash/par_hash.cpp b/src/hash/par_hash/par_hash.cpp index 4b0c7c466..0ba3f5a4f 100644 --- a/src/hash/par_hash/par_hash.cpp +++ b/src/hash/par_hash/par_hash.cpp @@ -77,7 +77,7 @@ HashFunction* Parallel::clone() const /* * Clear memory of sensitive data */ -void Parallel::clear() throw() +void Parallel::clear() { for(u32bit j = 0; j != hashes.size(); ++j) hashes[j]->clear(); diff --git a/src/hash/par_hash/par_hash.h b/src/hash/par_hash/par_hash.h index 7e75c27be..874e491b1 100644 --- a/src/hash/par_hash/par_hash.h +++ b/src/hash/par_hash/par_hash.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL Parallel : public HashFunction { public: - void clear() throw(); + void clear(); std::string name() const; HashFunction* clone() const; diff --git a/src/hash/rmd128/info.txt b/src/hash/rmd128/info.txt index 402271da5..0a1ef2c74 100644 --- a/src/hash/rmd128/info.txt +++ b/src/hash/rmd128/info.txt @@ -2,13 +2,6 @@ realname "RIPEMD-128" define RIPEMD_128 -load_on auto - -<add> -rmd128.cpp -rmd128.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/rmd128/rmd128.cpp b/src/hash/rmd128/rmd128.cpp index 8b2c0ccf8..899e50914 100644 --- a/src/hash/rmd128/rmd128.cpp +++ b/src/hash/rmd128/rmd128.cpp @@ -159,7 +159,7 @@ void RIPEMD_128::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void RIPEMD_128::clear() throw() +void RIPEMD_128::clear() { MDx_HashFunction::clear(); M.clear(); diff --git a/src/hash/rmd128/rmd128.h b/src/hash/rmd128/rmd128.h index 031ae5746..d9cb4ebb4 100644 --- a/src/hash/rmd128/rmd128.h +++ b/src/hash/rmd128/rmd128.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL RIPEMD_128 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "RIPEMD-128"; } HashFunction* clone() const { return new RIPEMD_128; } RIPEMD_128() : MDx_HashFunction(16, 64, false, true) { clear(); } diff --git a/src/hash/rmd160/info.txt b/src/hash/rmd160/info.txt index af4b5c230..225106afc 100644 --- a/src/hash/rmd160/info.txt +++ b/src/hash/rmd160/info.txt @@ -2,13 +2,6 @@ realname "RIPEMD-160" define RIPEMD_160 -load_on auto - -<add> -rmd160.cpp -rmd160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/rmd160/rmd160.cpp b/src/hash/rmd160/rmd160.cpp index 863de8487..2baf5ab08 100644 --- a/src/hash/rmd160/rmd160.cpp +++ b/src/hash/rmd160/rmd160.cpp @@ -196,7 +196,7 @@ void RIPEMD_160::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void RIPEMD_160::clear() throw() +void RIPEMD_160::clear() { MDx_HashFunction::clear(); M.clear(); diff --git a/src/hash/rmd160/rmd160.h b/src/hash/rmd160/rmd160.h index f2babc582..aee007b98 100644 --- a/src/hash/rmd160/rmd160.h +++ b/src/hash/rmd160/rmd160.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL RIPEMD_160 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "RIPEMD-160"; } HashFunction* clone() const { return new RIPEMD_160; } RIPEMD_160() : MDx_HashFunction(20, 64, false, true) { clear(); } diff --git a/src/hash/sha1/info.txt b/src/hash/sha1/info.txt index a0ae30b4b..8915f9ebd 100644 --- a/src/hash/sha1/info.txt +++ b/src/hash/sha1/info.txt @@ -2,13 +2,6 @@ realname "SHA-1" define SHA1 -load_on auto - -<add> -sha160.cpp -sha160.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/sha1/sha160.cpp b/src/hash/sha1/sha160.cpp index 45323a11b..a9e6880a7 100644 --- a/src/hash/sha1/sha160.cpp +++ b/src/hash/sha1/sha160.cpp @@ -130,7 +130,7 @@ void SHA_160::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void SHA_160::clear() throw() +void SHA_160::clear() { MDx_HashFunction::clear(); W.clear(); diff --git a/src/hash/sha1/sha160.h b/src/hash/sha1/sha160.h index 232cf0322..142c6bf17 100644 --- a/src/hash/sha1/sha160.h +++ b/src/hash/sha1/sha160.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL SHA_160 : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "SHA-160"; } HashFunction* clone() const { return new SHA_160; } SHA_160(); diff --git a/src/hash/sha1_amd64/info.txt b/src/hash/sha1_amd64/info.txt index ddbc7d380..183658ac7 100644 --- a/src/hash/sha1_amd64/info.txt +++ b/src/hash/sha1_amd64/info.txt @@ -4,12 +4,6 @@ define SHA1_AMD64 load_on asm_ok -<add> -sha1_amd64_imp.S -sha1_amd64.cpp -sha1_amd64.h -</add> - <arch> amd64 </arch> diff --git a/src/hash/sha1_ia32/info.txt b/src/hash/sha1_ia32/info.txt index bfb321145..e7709454f 100644 --- a/src/hash/sha1_ia32/info.txt +++ b/src/hash/sha1_ia32/info.txt @@ -4,12 +4,6 @@ define SHA1_IA32 load_on asm_ok -<add> -sha1_ia32_imp.S -sha1_ia32.cpp -sha1_ia32.h -</add> - <arch> ia32 </arch> diff --git a/src/hash/sha1_sse2/info.txt b/src/hash/sha1_sse2/info.txt index b8d693b70..4a7a1b5e9 100644 --- a/src/hash/sha1_sse2/info.txt +++ b/src/hash/sha1_sse2/info.txt @@ -2,26 +2,6 @@ realname "SHA-1 (SSE2)" define SHA1_SSE2 -load_on auto - -<add> -sha1_sse2_imp.cpp -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..5ee222cca 100644 --- a/src/hash/sha1_sse2/sha1_sse2_imp.cpp +++ b/src/hash/sha1_sse2/sha1_sse2_imp.cpp @@ -1,27 +1,18 @@ -/* this code is public domain. - - * dean gaudet <[email protected]> - - * this code was inspired by this paper: - - * SHA: A Design for Parallel Architectures? - * Antoon Bosselaers, Ren�e Govaerts and Joos Vandewalle - * <http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9700.pdf> - - * more information available on this implementation here: - - * http://arctic.org/~dean/crypto/sha1.html - - * version: 2 - */ +/* +* SHA-1 using SSE2 +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ /* - * Lightly modified for Botan, tested under GCC 4.1.1 and ICC 9.1 - * on a Linux/Core2 system. +* Based on public domain code by Dean Gaudet <[email protected]> +* http://arctic.org/~dean/crypto/sha1.html +*/ - */ #include <botan/sha1_sse2.h> -#include <xmmintrin.h> +#include <botan/rotate.h> +#include <emmintrin.h> namespace Botan { @@ -30,21 +21,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 +40,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 +94,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 +156,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 +183,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/hash/sha2/info.txt b/src/hash/sha2/info.txt index 9b92ff385..8cc50fa41 100644 --- a/src/hash/sha2/info.txt +++ b/src/hash/sha2/info.txt @@ -2,15 +2,6 @@ realname "SHA-2 (224, 256, 384, 512)" define SHA2 -load_on auto - -<add> -sha2_32.cpp -sha2_32.h -sha2_64.cpp -sha2_64.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/sha2/sha2_32.cpp b/src/hash/sha2/sha2_32.cpp index 9da2ec23f..2a63eef25 100644 --- a/src/hash/sha2/sha2_32.cpp +++ b/src/hash/sha2/sha2_32.cpp @@ -62,7 +62,7 @@ void SHA_224_256_BASE::compress_n(const byte input[], u32bit blocks) for(u32bit j = 16; j != 64; ++j) W[j] = sigma(W[j- 2], 17, 19, 10) + W[j- 7] + - sigma(W[j-15], 7, 18, 3) + W[j-16]; + sigma(W[j-15], 7, 18, 3) + W[j-16]; F1(A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98); F1(H, A, B, C, D, E, F, G, W[ 1], 0x71374491); @@ -152,7 +152,7 @@ void SHA_224_256_BASE::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void SHA_224_256_BASE::clear() throw() +void SHA_224_256_BASE::clear() { MDx_HashFunction::clear(); W.clear(); @@ -161,7 +161,7 @@ void SHA_224_256_BASE::clear() throw() /* * Clear memory of sensitive data */ -void SHA_224::clear() throw() +void SHA_224::clear() { SHA_224_256_BASE::clear(); digest[0] = 0xc1059ed8; @@ -177,7 +177,7 @@ void SHA_224::clear() throw() /* * Clear memory of sensitive data */ -void SHA_256::clear() throw() +void SHA_256::clear() { SHA_224_256_BASE::clear(); digest[0] = 0x6A09E667; diff --git a/src/hash/sha2/sha2_32.h b/src/hash/sha2/sha2_32.h index 05083d19d..313eec676 100644 --- a/src/hash/sha2/sha2_32.h +++ b/src/hash/sha2/sha2_32.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL SHA_224_256_BASE : public MDx_HashFunction { protected: - void clear() throw(); + void clear(); SHA_224_256_BASE(u32bit out) : MDx_HashFunction(out, 64, true, true) { clear(); } @@ -36,7 +36,7 @@ class BOTAN_DLL SHA_224_256_BASE : public MDx_HashFunction class BOTAN_DLL SHA_224 : public SHA_224_256_BASE { public: - void clear() throw(); + void clear(); std::string name() const { return "SHA-224"; } HashFunction* clone() const { return new SHA_224; } SHA_224() : SHA_224_256_BASE(28) { clear(); } @@ -48,7 +48,7 @@ class BOTAN_DLL SHA_224 : public SHA_224_256_BASE class BOTAN_DLL SHA_256 : public SHA_224_256_BASE { public: - void clear() throw(); + void clear(); std::string name() const { return "SHA-256"; } HashFunction* clone() const { return new SHA_256; } SHA_256() : SHA_224_256_BASE(32) { clear (); } diff --git a/src/hash/sha2/sha2_64.cpp b/src/hash/sha2/sha2_64.cpp index e9b4c2e5a..3c771eb44 100644 --- a/src/hash/sha2/sha2_64.cpp +++ b/src/hash/sha2/sha2_64.cpp @@ -167,7 +167,7 @@ void SHA_384_512_BASE::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void SHA_384_512_BASE::clear() throw() +void SHA_384_512_BASE::clear() { MDx_HashFunction::clear(); W.clear(); @@ -176,7 +176,7 @@ void SHA_384_512_BASE::clear() throw() /* * Clear memory of sensitive data */ -void SHA_384::clear() throw() +void SHA_384::clear() { SHA_384_512_BASE::clear(); digest[0] = 0xCBBB9D5DC1059ED8; @@ -192,7 +192,7 @@ void SHA_384::clear() throw() /* * Clear memory of sensitive data */ -void SHA_512::clear() throw() +void SHA_512::clear() { SHA_384_512_BASE::clear(); digest[0] = 0x6A09E667F3BCC908; diff --git a/src/hash/sha2/sha2_64.h b/src/hash/sha2/sha2_64.h index dcc6dc83b..8e4d171f8 100644 --- a/src/hash/sha2/sha2_64.h +++ b/src/hash/sha2/sha2_64.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL SHA_384_512_BASE : public MDx_HashFunction { protected: - void clear() throw(); + void clear(); SHA_384_512_BASE(u32bit out) : MDx_HashFunction(out, 128, true, true, 16) {} @@ -37,7 +37,7 @@ class BOTAN_DLL SHA_384_512_BASE : public MDx_HashFunction class BOTAN_DLL SHA_384 : public SHA_384_512_BASE { public: - void clear() throw(); + void clear(); std::string name() const { return "SHA-384"; } HashFunction* clone() const { return new SHA_384; } SHA_384() : SHA_384_512_BASE(48) { clear(); } @@ -49,7 +49,7 @@ class BOTAN_DLL SHA_384 : public SHA_384_512_BASE class BOTAN_DLL SHA_512 : public SHA_384_512_BASE { public: - void clear() throw(); + void clear(); std::string name() const { return "SHA-512"; } HashFunction* clone() const { return new SHA_512; } SHA_512() : SHA_384_512_BASE(64) { clear(); } diff --git a/src/hash/skein/info.txt b/src/hash/skein/info.txt index bab8497c5..908033852 100644 --- a/src/hash/skein/info.txt +++ b/src/hash/skein/info.txt @@ -2,13 +2,6 @@ realname "Skein" define SKEIN_512 -load_on auto - -<add> -skein_512.cpp -skein_512.h -</add> - <requires> alloc </requires> diff --git a/src/hash/skein/skein_512.cpp b/src/hash/skein/skein_512.cpp index a48cfc186..b24efd5f7 100644 --- a/src/hash/skein/skein_512.cpp +++ b/src/hash/skein/skein_512.cpp @@ -183,7 +183,7 @@ HashFunction* Skein_512::clone() const return new Skein_512(output_bits, personalization); } -void Skein_512::clear() throw() +void Skein_512::clear() { H.clear(); T.clear(); diff --git a/src/hash/skein/skein_512.h b/src/hash/skein/skein_512.h index fa558fc0d..db8d3c8b7 100644 --- a/src/hash/skein/skein_512.h +++ b/src/hash/skein/skein_512.h @@ -22,7 +22,7 @@ class BOTAN_DLL Skein_512 : public HashFunction HashFunction* clone() const; std::string name() const; - void clear() throw(); + void clear(); private: void add_data(const byte input[], u32bit length); void final_result(byte out[]); diff --git a/src/hash/tiger/info.txt b/src/hash/tiger/info.txt index 7d4cd7177..92b5519c0 100644 --- a/src/hash/tiger/info.txt +++ b/src/hash/tiger/info.txt @@ -2,14 +2,6 @@ realname "Tiger" define TIGER -load_on auto - -<add> -tig_tab.cpp -tiger.cpp -tiger.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/tiger/tiger.cpp b/src/hash/tiger/tiger.cpp index e46f2cb77..975ea9b6b 100644 --- a/src/hash/tiger/tiger.cpp +++ b/src/hash/tiger/tiger.cpp @@ -129,7 +129,7 @@ void Tiger::mix(u64bit X[8]) /* * Clear memory of sensitive data */ -void Tiger::clear() throw() +void Tiger::clear() { MDx_HashFunction::clear(); X.clear(); diff --git a/src/hash/tiger/tiger.h b/src/hash/tiger/tiger.h index 63184a938..86ddcd270 100644 --- a/src/hash/tiger/tiger.h +++ b/src/hash/tiger/tiger.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL Tiger : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const; HashFunction* clone() const { return new Tiger(OUTPUT_LENGTH); } Tiger(u32bit = 24, u32bit = 3); diff --git a/src/hash/whirlpool/info.txt b/src/hash/whirlpool/info.txt index be55b5c3b..4fe4b2b25 100644 --- a/src/hash/whirlpool/info.txt +++ b/src/hash/whirlpool/info.txt @@ -2,14 +2,6 @@ realname "Whirlpool" define WHIRLPOOL -load_on auto - -<add> -whrl_tab.cpp -whrlpool.cpp -whrlpool.h -</add> - <requires> mdx_hash </requires> diff --git a/src/hash/whirlpool/whrlpool.cpp b/src/hash/whirlpool/whrlpool.cpp index 8548d6192..b7a02a9b6 100644 --- a/src/hash/whirlpool/whrlpool.cpp +++ b/src/hash/whirlpool/whrlpool.cpp @@ -136,7 +136,7 @@ void Whirlpool::copy_out(byte output[]) /* * Clear memory of sensitive data */ -void Whirlpool::clear() throw() +void Whirlpool::clear() { MDx_HashFunction::clear(); M.clear(); diff --git a/src/hash/whirlpool/whrlpool.h b/src/hash/whirlpool/whrlpool.h index b72ff609f..34b4d2302 100644 --- a/src/hash/whirlpool/whrlpool.h +++ b/src/hash/whirlpool/whrlpool.h @@ -18,7 +18,7 @@ namespace Botan { class BOTAN_DLL Whirlpool : public MDx_HashFunction { public: - void clear() throw(); + void clear(); std::string name() const { return "Whirlpool"; } HashFunction* clone() const { return new Whirlpool; } Whirlpool() : MDx_HashFunction(64, 64, true, true, 32) { clear(); } diff --git a/src/kdf/kdf.h b/src/kdf/kdf.h index 70f636b6c..67078218f 100644 --- a/src/kdf/kdf.h +++ b/src/kdf/kdf.h @@ -22,6 +22,7 @@ class BOTAN_DLL KDF SecureVector<byte> derive_key(u32bit key_len, const MemoryRegion<byte>& secret, const std::string& salt = "") const; + SecureVector<byte> derive_key(u32bit key_len, const MemoryRegion<byte>& secret, const MemoryRegion<byte>& salt) const; @@ -33,14 +34,17 @@ class BOTAN_DLL KDF SecureVector<byte> derive_key(u32bit key_len, const byte secret[], u32bit secret_len, const std::string& salt = "") const; + SecureVector<byte> derive_key(u32bit key_len, const byte secret[], u32bit secret_len, const byte salt[], u32bit salt_len) const; virtual ~KDF() {} private: - virtual SecureVector<byte> derive(u32bit, const byte[], u32bit, - const byte[], u32bit) const = 0; + virtual SecureVector<byte> + derive(u32bit key_len, + const byte secret[], u32bit secret_len, + const byte salt[], u32bit salt_len) const = 0; }; /* @@ -50,7 +54,7 @@ class BOTAN_DLL MGF { public: virtual void mask(const byte in[], u32bit in_len, - byte out[], u32bit out_len) const = 0; + byte out[], u32bit out_len) const = 0; virtual ~MGF() {} }; diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp index 3275c6493..ca454458b 100644 --- a/src/libstate/libstate.cpp +++ b/src/libstate/libstate.cpp @@ -7,6 +7,7 @@ #include <botan/libstate.h> #include <botan/init.h> +#include <botan/selftest.h> #include <botan/engine.h> #include <botan/stl_util.h> #include <botan/mutex.h> @@ -212,7 +213,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); @@ -302,6 +303,9 @@ void Library_State::initialize(bool thread_safe) engines.push_back(new Default_Engine); m_algorithm_factory = new Algorithm_Factory(engines, *mutex_factory); + + if(!passes_self_tests(algorithm_factory())) + throw Self_Test_Failure("Startup self tests failed"); } /* 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..224d2e509 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 */ @@ -14,28 +14,50 @@ namespace Botan { namespace { -std::vector<std::string> -parse_and_deref_aliases(const std::string& algo_spec) +std::string make_arg( + const std::vector<std::pair<u32bit, std::string> >& name, u32bit start) { - std::vector<std::string> parts = parse_algorithm_name(algo_spec); - std::vector<std::string> out; + std::string output = name[start].second; + u32bit level = name[start].first; - for(size_t i = 0; i != parts.size(); ++i) + u32bit paren_depth = 0; + + for(u32bit i = start + 1; i != name.size(); ++i) { - std::string part_i = global_state().deref_alias(parts[i]); + if(name[i].first <= name[start].first) + break; - if(i == 0 && part_i.find_first_of(",()") != std::string::npos) + if(name[i].first > level) { - std::vector<std::string> parts_i = parse_and_deref_aliases(part_i); - - for(size_t j = 0; j != parts_i.size(); ++j) - out.push_back(parts_i[j]); + output += '(' + name[i].second; + ++paren_depth; + } + else if(name[i].first < level) + { + output += ")," + name[i].second; + --paren_depth; } else - out.push_back(part_i); + { + if(output[output.size() - 1] != '(') + output += ","; + output += name[i].second; + } + + level = name[i].first; } - return out; + for(u32bit i = 0; i != paren_depth; ++i) + output += ')'; + + return output; + } + +std::pair<u32bit, std::string> +deref_aliases(const std::pair<u32bit, std::string>& in) + { + return std::make_pair(in.first, + global_state().deref_alias(in.second)); } } @@ -44,31 +66,101 @@ SCAN_Name::SCAN_Name(const std::string& algo_spec) { orig_algo_spec = algo_spec; - name = parse_and_deref_aliases(algo_spec); + std::vector<std::pair<u32bit, std::string> > name; + u32bit level = 0; + std::pair<u32bit, std::string> accum = std::make_pair(level, ""); + + for(u32bit i = 0; i != algo_spec.size(); ++i) + { + char c = algo_spec[i]; + + if(c == '/' || c == ',' || c == '(' || c == ')') + { + if(c == '(') + ++level; + else if(c == ')') + { + if(level == 0) + throw Decoding_Error("Bad SCAN name " + algo_spec); + --level; + } + + if(c == '/' && level > 0) + accum.second.push_back(c); + else + { + if(accum.second != "") + name.push_back(deref_aliases(accum)); + accum = std::make_pair(level, ""); + } + } + else + accum.second.push_back(c); + } + + if(accum.second != "") + name.push_back(deref_aliases(accum)); - if(name.size() == 0) + if(level != 0 || name.size() == 0) throw Decoding_Error("Bad SCAN name " + algo_spec); + + alg_name = name[0].second; + + bool in_modes = false; + + for(u32bit i = 1; i != name.size(); ++i) + { + if(name[i].first == 0) + { + mode_info.push_back(make_arg(name, i)); + in_modes = true; + } + else if(name[i].first == 1 && !in_modes) + args.push_back(make_arg(name, i)); + } + } + +std::string SCAN_Name::algo_name_and_args() const + { + std::string out; + + out = algo_name(); + + if(arg_count()) + { + out += '('; + for(u32bit i = 0; i != arg_count(); ++i) + { + out += arg(i); + if(i != arg_count() - 1) + out += ','; + } + out += ')'; + + } + + return out; } std::string SCAN_Name::arg(u32bit i) const { if(i >= arg_count()) throw std::range_error("SCAN_Name::argument"); - return name[i+1]; + return args[i]; } std::string SCAN_Name::arg(u32bit i, const std::string& def_value) const { if(i >= arg_count()) return def_value; - return name[i+1]; + return args[i]; } u32bit SCAN_Name::arg_as_u32bit(u32bit i, u32bit def_value) const { if(i >= arg_count()) return def_value; - return to_u32bit(name[i+1]); + return to_u32bit(args[i]); } } diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h index 9e7af40d6..ced5f3e15 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 */ @@ -35,12 +35,17 @@ class SCAN_Name /** @return the algorithm name */ - std::string algo_name() const { return name[0]; } + std::string algo_name() const { return alg_name; } + + /** + @return the algorithm name plus any arguments + */ + std::string algo_name_and_args() const; /** @return the number of arguments */ - u32bit arg_count() const { return name.size() - 1; } + u32bit arg_count() const { return args.size(); } /** @return if the number of arguments is between lower and upper @@ -67,9 +72,24 @@ class SCAN_Name @return the ith argument as a u32bit, or the default value */ u32bit arg_as_u32bit(u32bit i, u32bit def_value) const; + + /** + @return the cipher mode (if any) + */ + std::string cipher_mode() const + { return (mode_info.size() >= 1) ? mode_info[0] : ""; } + + /** + @return the cipher mode padding (if any) + */ + std::string cipher_mode_pad() const + { return (mode_info.size() >= 2) ? mode_info[1] : ""; } + private: std::string orig_algo_spec; - std::vector<std::string> name; + std::string alg_name; + std::vector<std::string> args; + std::vector<std::string> mode_info; }; } diff --git a/src/mac/cbc_mac/cbc_mac.cpp b/src/mac/cbc_mac/cbc_mac.cpp index f5d9e1567..0617e3e90 100644 --- a/src/mac/cbc_mac/cbc_mac.cpp +++ b/src/mac/cbc_mac/cbc_mac.cpp @@ -62,7 +62,7 @@ void CBC_MAC::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void CBC_MAC::clear() throw() +void CBC_MAC::clear() { e->clear(); state.clear(); diff --git a/src/mac/cbc_mac/cbc_mac.h b/src/mac/cbc_mac/cbc_mac.h index d17d792d3..15026c0a9 100644 --- a/src/mac/cbc_mac/cbc_mac.h +++ b/src/mac/cbc_mac/cbc_mac.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL CBC_MAC : public MessageAuthenticationCode { public: - void clear() throw(); + void clear(); std::string name() const; MessageAuthenticationCode* clone() const; diff --git a/src/mac/cmac/cmac.cpp b/src/mac/cmac/cmac.cpp index 84aa61e03..58923138b 100644 --- a/src/mac/cmac/cmac.cpp +++ b/src/mac/cmac/cmac.cpp @@ -101,7 +101,7 @@ void CMAC::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void CMAC::clear() throw() +void CMAC::clear() { e->clear(); state.clear(); diff --git a/src/mac/cmac/cmac.h b/src/mac/cmac/cmac.h index 5a6deb7b0..8297e5ea1 100644 --- a/src/mac/cmac/cmac.h +++ b/src/mac/cmac/cmac.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL CMAC : public MessageAuthenticationCode { public: - void clear() throw(); + void clear(); std::string name() const; MessageAuthenticationCode* clone() const; diff --git a/src/mac/hmac/hmac.cpp b/src/mac/hmac/hmac.cpp index 717e2640c..99be479fa 100644 --- a/src/mac/hmac/hmac.cpp +++ b/src/mac/hmac/hmac.cpp @@ -58,7 +58,7 @@ void HMAC::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void HMAC::clear() throw() +void HMAC::clear() { hash->clear(); i_key.clear(); diff --git a/src/mac/hmac/hmac.h b/src/mac/hmac/hmac.h index 932af71fc..62bb69853 100644 --- a/src/mac/hmac/hmac.h +++ b/src/mac/hmac/hmac.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL HMAC : public MessageAuthenticationCode { public: - void clear() throw(); + void clear(); std::string name() const; MessageAuthenticationCode* clone() const; 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/mac/mac.h b/src/mac/mac.h index 3ec5fff5f..7c73a2900 100644 --- a/src/mac/mac.h +++ b/src/mac/mac.h @@ -43,7 +43,7 @@ class BOTAN_DLL MessageAuthenticationCode : public BufferedComputation, /** * Reset the internal state of this object. */ - virtual void clear() throw() = 0; + virtual void clear() = 0; MessageAuthenticationCode(u32bit mac_len, u32bit key_min, diff --git a/src/mac/ssl3mac/ssl3_mac.cpp b/src/mac/ssl3mac/ssl3_mac.cpp index c29296ced..23a636424 100644 --- a/src/mac/ssl3mac/ssl3_mac.cpp +++ b/src/mac/ssl3mac/ssl3_mac.cpp @@ -46,7 +46,7 @@ void SSL3_MAC::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void SSL3_MAC::clear() throw() +void SSL3_MAC::clear() { hash->clear(); i_key.clear(); diff --git a/src/mac/ssl3mac/ssl3_mac.h b/src/mac/ssl3mac/ssl3_mac.h index dcaf7f404..828b072ed 100644 --- a/src/mac/ssl3mac/ssl3_mac.h +++ b/src/mac/ssl3mac/ssl3_mac.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL SSL3_MAC : public MessageAuthenticationCode { public: - void clear() throw(); + void clear(); std::string name() const; MessageAuthenticationCode* clone() const; diff --git a/src/mac/x919_mac/x919_mac.cpp b/src/mac/x919_mac/x919_mac.cpp index ef89cac9c..52260494a 100644 --- a/src/mac/x919_mac/x919_mac.cpp +++ b/src/mac/x919_mac/x919_mac.cpp @@ -63,7 +63,7 @@ void ANSI_X919_MAC::key_schedule(const byte key[], u32bit length) /* * Clear memory of sensitive data */ -void ANSI_X919_MAC::clear() throw() +void ANSI_X919_MAC::clear() { e->clear(); d->clear(); diff --git a/src/mac/x919_mac/x919_mac.h b/src/mac/x919_mac/x919_mac.h index 1c2a06bee..a4690fdcd 100644 --- a/src/mac/x919_mac/x919_mac.h +++ b/src/mac/x919_mac/x919_mac.h @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL ANSI_X919_MAC : public MessageAuthenticationCode { public: - void clear() throw(); + void clear(); std::string name() const; MessageAuthenticationCode* clone() const; diff --git a/src/math/bigint/bigint.cpp b/src/math/bigint/bigint.cpp index 926bedc02..63bdc3605 100644 --- a/src/math/bigint/bigint.cpp +++ b/src/math/bigint/bigint.cpp @@ -9,7 +9,7 @@ #include <botan/mp_core.h> #include <botan/loadstor.h> #include <botan/parsing.h> -#include <botan/util.h> +#include <botan/rounding.h> namespace Botan { diff --git a/src/math/bigint/mp_amd64/mp_asmi.h b/src/math/bigint/mp_amd64/mp_asmi.h index 8bccbaaf4..1a3ac1aaa 100644 --- a/src/math/bigint/mp_amd64/mp_asmi.h +++ b/src/math/bigint/mp_amd64/mp_asmi.h @@ -70,20 +70,12 @@ extern "C" { */ inline word word_add(word x, word y, word* carry) { -#if 0 asm( ADD_OR_SUBTRACT(ASM("adcq %[y],%[x]")) : [x]"=r"(x), [carry]"=r"(*carry) : "0"(x), [y]"rm"(y), "1"(*carry) : "cc"); return x; -#else - word z = x + y; - word c1 = (z < x); - z += *carry; - *carry = c1 | (z < *carry); - return z; -#endif } /* diff --git a/src/math/bigint/mp_ia32/mp_asmi.h b/src/math/bigint/mp_ia32/mp_asmi.h index 28b99abcc..46bf302d5 100644 --- a/src/math/bigint/mp_ia32/mp_asmi.h +++ b/src/math/bigint/mp_ia32/mp_asmi.h @@ -70,20 +70,12 @@ extern "C" { */ inline word word_add(word x, word y, word* carry) { -#if 0 asm( ADD_OR_SUBTRACT(ASM("adcl %[y],%[x]")) : [x]"=r"(x), [carry]"=r"(*carry) : "0"(x), [y]"rm"(y), "1"(*carry) : "cc"); return x; -#else - word z = x + y; - word c1 = (z < x); - z += *carry; - *carry = c1 | (z < *carry); - return z; -#endif } /* diff --git a/src/math/gfpmath/curve_gfp.cpp b/src/math/gfpmath/curve_gfp.cpp index e12ade081..9a3ffd482 100644 --- a/src/math/gfpmath/curve_gfp.cpp +++ b/src/math/gfpmath/curve_gfp.cpp @@ -1,11 +1,11 @@ -/****** +/* * Elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke * 2008 Jack Lloyd -******/ +* +* Distributed under the terms of the Botan license +*/ #include <botan/curve_gfp.h> #include <botan/bigint.h> diff --git a/src/math/gfpmath/gfp_element.cpp b/src/math/gfpmath/gfp_element.cpp index b71809301..8ae9b3c3a 100644 --- a/src/math/gfpmath/gfp_element.cpp +++ b/src/math/gfpmath/gfp_element.cpp @@ -1,13 +1,15 @@ -/****** - * Arithmetic for prime fields GF(p) (source file) - * - * (C) 2007 Martin Doering - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Arithmetic for prime fields GF(p) +* +* (C) 2007 Martin Doering +* Christoph Ludwig +* Falko Strenzke +* +* Distributed under the terms of the Botan license +*/ #include <botan/gfp_element.h> #include <botan/numthry.h> @@ -15,8 +17,8 @@ #include <botan/mp_types.h> #include <botan/mp_asm.h> #include <botan/mp_asmi.h> -#include <assert.h> #include <ostream> +#include <assert.h> namespace Botan { @@ -66,7 +68,9 @@ void inner_montg_mult_sos(word result[], const word* a_bar, const word* b_bar, c while (C > 0) { // we need not worry here about C > 1, because the other operand is zero - word tmp = word_add(t[i+s+cnt], 0, &C); + + word tmp = t[i+s+cnt] + C; + C = (tmp < t[i+s+cnt]); t[i+s+cnt] = tmp; cnt++; } diff --git a/src/math/gfpmath/gfp_element.h b/src/math/gfpmath/gfp_element.h index 4e0ee985b..18d9e51f9 100644 --- a/src/math/gfpmath/gfp_element.h +++ b/src/math/gfpmath/gfp_element.h @@ -1,13 +1,15 @@ -/****** - * Arithmetic for prime fields GF(p) (header file) - * - * (C) 2007 Martin Doering - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Arithmetic for prime fields GF(p) +* +* (C) 2007 Martin Doering +* Christoph Ludwig +* Falko Strenzke +* +* Distributed under the terms of the Botan license +*/ #ifndef BOTAN_GFP_ELEMENT_H__ #define BOTAN_GFP_ELEMENT_H__ @@ -26,11 +28,11 @@ namespace Botan { -struct Illegal_Transformation : public Exception +struct BOTAN_DLL Illegal_Transformation : public Exception { Illegal_Transformation(const std::string& err = - "Requested transformation is not possible") - : Exception(err) {} + "Requested transformation is not possible") : + Exception(err) {} }; /** @@ -39,23 +41,6 @@ struct Illegal_Transformation : public Exception */ class BOTAN_DLL GFpElement { - private: - std::tr1::shared_ptr<GFpModulus> mp_mod; - mutable BigInt m_value; // ordinary residue or m-residue respectively - mutable BigInt workspace; - - // ***************************************** - // data members for montgomery multiplication - mutable bool m_use_montgm; - //mutable BigInt m_mres; - // this bool tells use whether the m_mres carries - // the actual value (in this case mValue doesn´t) - mutable bool m_is_trf; - - void ensure_montgm_precomp() const; - void trf_to_mres() const; - void trf_to_ordres() const; - public: /** construct an element of GF(p) with the given value. @@ -260,7 +245,22 @@ class BOTAN_DLL GFpElement * @param other The value to swap with */ void swap(GFpElement& other); + private: + void ensure_montgm_precomp() const; + void trf_to_mres() const; + void trf_to_ordres() const; + + std::tr1::shared_ptr<GFpModulus> mp_mod; + mutable BigInt m_value; // ordinary residue or m-residue respectively + mutable BigInt workspace; + // ***************************************** + // data members for montgomery multiplication + mutable bool m_use_montgm; + //mutable BigInt m_mres; + // this bool tells use whether the m_mres carries + // the actual value (in this case mValue doesn´t) + mutable bool m_is_trf; }; // relational operators diff --git a/src/math/gfpmath/gfp_modulus.h b/src/math/gfpmath/gfp_modulus.h index b5c085775..8e37e9a73 100644 --- a/src/math/gfpmath/gfp_modulus.h +++ b/src/math/gfpmath/gfp_modulus.h @@ -1,39 +1,33 @@ -/****** - * Modulus and related data for a specific - * implementation of GF(p) (header file) - * - * (C) 2008 Martin Döring - * Christoph Ludwig - * Falko Strenzke - ******/ +/* +* Modulus and related data for a specific implementation of GF(p) +* +* (C) 2008 Martin Döring +* <[email protected]> +* Christoph Ludwig +* <[email protected]> +* Falko Strenzke +* <[email protected]> +* +* Distributed under the terms of the Botan license +*/ #ifndef BOTAN_GFP_MODULUS_H__ #define BOTAN_GFP_MODULUS_H__ #include <botan/bigint.h> -namespace Botan -{ +namespace Botan { class BOTAN_DLL GFpElement; + /** -* This class represents a GFpElement modulus including the modulus related -* values necessary for the montgomery multiplication. -* -* Distributed under the terms of the Botan license +* This class represents a GFpElement modulus including the modulus +* related values necessary for the montgomery multiplication. */ class BOTAN_DLL GFpModulus { - friend class GFpElement; - private: - BigInt m_p; // the modulus itself - mutable BigInt m_p_dash; - mutable BigInt m_r; - mutable BigInt m_r_inv; public: + friend class GFpElement; /** * Construct a GF(P)-Modulus from a BigInt @@ -119,9 +113,14 @@ class BOTAN_DLL GFpModulus return m_p_dash; } // default cp-ctor, op= are fine + + private: + BigInt m_p; // the modulus itself + mutable BigInt m_p_dash; + mutable BigInt m_r; + mutable BigInt m_r_inv; }; } #endif - diff --git a/src/math/gfpmath/point_gfp.cpp b/src/math/gfpmath/point_gfp.cpp index 9139c3ef9..b67631f7b 100644 --- a/src/math/gfpmath/point_gfp.cpp +++ b/src/math/gfpmath/point_gfp.cpp @@ -1,12 +1,11 @@ -/****** -* Arithmetic for point groups of elliptic curves -* over GF(p) (source file) +/* +* Arithmetic for point groups of elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke * 2008 Jack Lloyd -******/ +* +* Distributed under the terms of the Botan license +*/ #include <botan/point_gfp.h> #include <botan/numthry.h> @@ -688,8 +687,6 @@ void PointGFp::turn_on_sp_red_mul() const * returns a point equivalent to *this but were * Z has value one, i.e. x and y correspond to * their values in affine coordinates -* -* Distributed under the terms of the Botan license */ PointGFp const PointGFp::get_z_to_one() const { diff --git a/src/math/gfpmath/point_gfp.h b/src/math/gfpmath/point_gfp.h index 771605efc..62b3bc7da 100644 --- a/src/math/gfpmath/point_gfp.h +++ b/src/math/gfpmath/point_gfp.h @@ -1,10 +1,8 @@ /* -* Arithmetic over GF(p) +* Arithmetic for point groups of elliptic curves over GF(p) * -* (C) 2007 Martin Doering -* Christoph Ludwig -* Falko Strenzke -* (C) 2008 Jack Lloyd +* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke +* 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/math/numbertheory/mp_numth.cpp b/src/math/numbertheory/mp_numth.cpp index 45a398440..2cb36b8a3 100644 --- a/src/math/numbertheory/mp_numth.cpp +++ b/src/math/numbertheory/mp_numth.cpp @@ -7,7 +7,7 @@ #include <botan/numthry.h> #include <botan/mp_core.h> -#include <botan/util.h> +#include <botan/rounding.h> #include <algorithm> namespace Botan { diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp deleted file mode 100644 index 9eb42ec5a..000000000 --- a/src/modes/ctr/ctr.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* CTR Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ctr.h> -#include <botan/xor_buf.h> -#include <algorithm> - -namespace Botan { - -/* -* CTR-BE Constructor -*/ -CTR_BE::CTR_BE(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) - { - } - -/* -* CTR-BE Constructor -*/ -CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key, - const InitializationVector& iv) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) - { - set_key(key); - set_iv(iv); - } - -/* -* 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); - input += copied; - length -= copied; - position += copied; - - if(position == BLOCK_SIZE) - increment_counter(); - - while(length >= BLOCK_SIZE) - { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); - - input += BLOCK_SIZE; - length -= BLOCK_SIZE; - increment_counter(); - } - - xor_buf(buffer + position, input, length); - send(buffer + position, length); - position += length; - } - -/* -* Increment the counter and update the buffer -*/ -void CTR_BE::increment_counter() - { - for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) - if(++state[j]) - break; - cipher->encrypt(state, buffer); - position = 0; - } - -} diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h deleted file mode 100644 index aa0db5761..000000000 --- a/src/modes/ctr/ctr.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -* CTR Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_COUNTER_MODE_H__ -#define BOTAN_COUNTER_MODE_H__ - -#include <botan/modebase.h> -#include <botan/modebase.h> - -namespace Botan { - -/* -* CTR-BE Mode -*/ -class BOTAN_DLL CTR_BE : public BlockCipherMode - { - public: - CTR_BE(BlockCipher*); - CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&); - private: - void write(const byte[], u32bit); - void increment_counter(); - }; - -} - -#endif 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/mode_pad/mode_pad.cpp b/src/modes/mode_pad/mode_pad.cpp index b8badd7a7..2204c28b5 100644 --- a/src/modes/mode_pad/mode_pad.cpp +++ b/src/modes/mode_pad/mode_pad.cpp @@ -7,7 +7,6 @@ #include <botan/mode_pad.h> #include <botan/exceptn.h> -#include <botan/util.h> namespace Botan { 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/ofb/ofb.cpp b/src/modes/ofb/ofb.cpp deleted file mode 100644 index cb40fdeaa..000000000 --- a/src/modes/ofb/ofb.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -* OFB Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ofb.h> -#include <botan/xor_buf.h> -#include <algorithm> - -namespace Botan { - -/* -* OFB Constructor -*/ -OFB::OFB(BlockCipher* ciph) : - BlockCipherMode(ciph, "OFB", ciph->BLOCK_SIZE, 2) - { - } - -/* -* OFB Constructor -*/ -OFB::OFB(BlockCipher* ciph, const SymmetricKey& key, - const InitializationVector& iv) : - BlockCipherMode(ciph, "OFB", ciph->BLOCK_SIZE, 2) - { - set_key(key); - set_iv(iv); - } - -/* -* OFB Encryption/Decryption -*/ -void OFB::write(const byte input[], u32bit length) - { - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer, input, state + position, copied); - send(buffer, copied); - input += copied; - length -= copied; - position += copied; - - if(position == BLOCK_SIZE) - { - cipher->encrypt(state); - position = 0; - } - - while(length >= BLOCK_SIZE) - { - xor_buf(buffer, input, state, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); - - input += BLOCK_SIZE; - length -= BLOCK_SIZE; - cipher->encrypt(state); - } - - xor_buf(buffer, input, state + position, length); - send(buffer, length); - position += length; - } - -} diff --git a/src/modes/ofb/ofb.h b/src/modes/ofb/ofb.h deleted file mode 100644 index a3aadc137..000000000 --- a/src/modes/ofb/ofb.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -* OFB Mode -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_OUTPUT_FEEDBACK_MODE_H__ -#define BOTAN_OUTPUT_FEEDBACK_MODE_H__ - -#include <botan/modebase.h> -#include <botan/block_cipher.h> - -namespace Botan { - -/* -* OFB Mode -*/ -class BOTAN_DLL OFB : public BlockCipherMode - { - public: - OFB(BlockCipher* cipher); - - OFB(BlockCipher* cipher, - const SymmetricKey& key, - const InitializationVector& iv); - private: - void write(const byte[], u32bit); - }; - -} - -#endif 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/pk_pad/emsa.h b/src/pk_pad/emsa.h index e2491e40f..8b19d3cb2 100644 --- a/src/pk_pad/emsa.h +++ b/src/pk_pad/emsa.h @@ -27,7 +27,7 @@ class BOTAN_DLL EMSA RandomNumberGenerator& rng) = 0; virtual bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw() = 0; + u32bit) = 0; virtual ~EMSA() {} }; diff --git a/src/pk_pad/emsa1/emsa1.cpp b/src/pk_pad/emsa1/emsa1.cpp index 26d709c28..0ae7e8d2d 100644 --- a/src/pk_pad/emsa1/emsa1.cpp +++ b/src/pk_pad/emsa1/emsa1.cpp @@ -72,7 +72,7 @@ SecureVector<byte> EMSA1::encoding_of(const MemoryRegion<byte>& msg, * EMSA1 Decode/Verify Operation */ bool EMSA1::verify(const MemoryRegion<byte>& coded, - const MemoryRegion<byte>& raw, u32bit key_bits) throw() + const MemoryRegion<byte>& raw, u32bit key_bits) { try { if(raw.size() != hash->OUTPUT_LENGTH) diff --git a/src/pk_pad/emsa1/emsa1.h b/src/pk_pad/emsa1/emsa1.h index a5dac07e2..d86020966 100644 --- a/src/pk_pad/emsa1/emsa1.h +++ b/src/pk_pad/emsa1/emsa1.h @@ -31,7 +31,7 @@ class BOTAN_DLL EMSA1 : public EMSA RandomNumberGenerator& rng); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); HashFunction* hash; }; diff --git a/src/pk_pad/emsa2/emsa2.cpp b/src/pk_pad/emsa2/emsa2.cpp index 168f9209e..74a045931 100644 --- a/src/pk_pad/emsa2/emsa2.cpp +++ b/src/pk_pad/emsa2/emsa2.cpp @@ -79,7 +79,7 @@ SecureVector<byte> EMSA2::encoding_of(const MemoryRegion<byte>& msg, */ bool EMSA2::verify(const MemoryRegion<byte>& coded, const MemoryRegion<byte>& raw, - u32bit key_bits) throw() + u32bit key_bits) { try { diff --git a/src/pk_pad/emsa2/emsa2.h b/src/pk_pad/emsa2/emsa2.h index 76888d1f6..7efc80873 100644 --- a/src/pk_pad/emsa2/emsa2.h +++ b/src/pk_pad/emsa2/emsa2.h @@ -29,7 +29,7 @@ class BOTAN_DLL EMSA2 : public EMSA RandomNumberGenerator& rng); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); SecureVector<byte> empty_hash; HashFunction* hash; diff --git a/src/pk_pad/emsa3/emsa3.cpp b/src/pk_pad/emsa3/emsa3.cpp index 4d50abd84..dc905a464 100644 --- a/src/pk_pad/emsa3/emsa3.cpp +++ b/src/pk_pad/emsa3/emsa3.cpp @@ -72,7 +72,7 @@ SecureVector<byte> EMSA3::encoding_of(const MemoryRegion<byte>& msg, */ bool EMSA3::verify(const MemoryRegion<byte>& coded, const MemoryRegion<byte>& raw, - u32bit key_bits) throw() + u32bit key_bits) { if(raw.size() != hash->OUTPUT_LENGTH) return false; @@ -137,7 +137,7 @@ SecureVector<byte> EMSA3_Raw::encoding_of(const MemoryRegion<byte>& msg, */ bool EMSA3_Raw::verify(const MemoryRegion<byte>& coded, const MemoryRegion<byte>& raw, - u32bit key_bits) throw() + u32bit key_bits) { try { diff --git a/src/pk_pad/emsa3/emsa3.h b/src/pk_pad/emsa3/emsa3.h index 301f2142a..c4a3d658b 100644 --- a/src/pk_pad/emsa3/emsa3.h +++ b/src/pk_pad/emsa3/emsa3.h @@ -32,7 +32,7 @@ class BOTAN_DLL EMSA3 : public EMSA RandomNumberGenerator& rng); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); private: HashFunction* hash; SecureVector<byte> hash_id; @@ -54,7 +54,7 @@ class BOTAN_DLL EMSA3_Raw : public EMSA RandomNumberGenerator& rng); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); private: SecureVector<byte> message; diff --git a/src/pk_pad/emsa4/emsa4.cpp b/src/pk_pad/emsa4/emsa4.cpp index cff9a1537..dba248662 100644 --- a/src/pk_pad/emsa4/emsa4.cpp +++ b/src/pk_pad/emsa4/emsa4.cpp @@ -68,7 +68,7 @@ SecureVector<byte> EMSA4::encoding_of(const MemoryRegion<byte>& msg, * EMSA4 Decode/Verify Operation */ bool EMSA4::verify(const MemoryRegion<byte>& const_coded, - const MemoryRegion<byte>& raw, u32bit key_bits) throw() + const MemoryRegion<byte>& raw, u32bit key_bits) { const u32bit HASH_SIZE = hash->OUTPUT_LENGTH; const u32bit KEY_BYTES = (key_bits + 7) / 8; diff --git a/src/pk_pad/emsa4/emsa4.h b/src/pk_pad/emsa4/emsa4.h index b716178a9..9e37684f5 100644 --- a/src/pk_pad/emsa4/emsa4.h +++ b/src/pk_pad/emsa4/emsa4.h @@ -31,7 +31,7 @@ class BOTAN_DLL EMSA4 : public EMSA SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit, RandomNumberGenerator& rng); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); u32bit SALT_SIZE; HashFunction* hash; diff --git a/src/pk_pad/emsa_raw/emsa_raw.cpp b/src/pk_pad/emsa_raw/emsa_raw.cpp index d5973ee55..5dfe20a50 100644 --- a/src/pk_pad/emsa_raw/emsa_raw.cpp +++ b/src/pk_pad/emsa_raw/emsa_raw.cpp @@ -42,7 +42,7 @@ SecureVector<byte> EMSA_Raw::encoding_of(const MemoryRegion<byte>& msg, */ bool EMSA_Raw::verify(const MemoryRegion<byte>& coded, const MemoryRegion<byte>& raw, - u32bit) throw() + u32bit) { return (coded == raw); } diff --git a/src/pk_pad/emsa_raw/emsa_raw.h b/src/pk_pad/emsa_raw/emsa_raw.h index 1b0ad516e..5f2eaa2fe 100644 --- a/src/pk_pad/emsa_raw/emsa_raw.h +++ b/src/pk_pad/emsa_raw/emsa_raw.h @@ -24,7 +24,7 @@ class BOTAN_DLL EMSA_Raw : public EMSA SecureVector<byte> encoding_of(const MemoryRegion<byte>&, u32bit, RandomNumberGenerator&); bool verify(const MemoryRegion<byte>&, const MemoryRegion<byte>&, - u32bit) throw(); + u32bit); SecureVector<byte> message; }; diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp index 0c9d02f0e..149bc5882 100644 --- a/src/pubkey/dh/dh.cpp +++ b/src/pubkey/dh/dh.cpp @@ -7,7 +7,7 @@ #include <botan/dh.h> #include <botan/numthry.h> -#include <botan/util.h> +#include <botan/workfactor.h> namespace Botan { diff --git a/src/pubkey/dl_group/dl_group.cpp b/src/pubkey/dl_group/dl_group.cpp index 81c5d5e1d..13ea03016 100644 --- a/src/pubkey/dl_group/dl_group.cpp +++ b/src/pubkey/dl_group/dl_group.cpp @@ -12,7 +12,7 @@ #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/pipe.h> -#include <botan/util.h> +#include <botan/workfactor.h> #include <botan/pem.h> namespace Botan { diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp index 6cfcc0619..0b5a6e681 100644 --- a/src/pubkey/ec_dompar/ec_dompar.cpp +++ b/src/pubkey/ec_dompar/ec_dompar.cpp @@ -1,3 +1,11 @@ +/* +* ECC Domain Parameters +* +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/ec_dompar.h> #include <botan/pubkey_enums.h> diff --git a/src/pubkey/ec_dompar/ec_dompar.h b/src/pubkey/ec_dompar/ec_dompar.h index 47971d802..5ea599c9d 100644 --- a/src/pubkey/ec_dompar/ec_dompar.h +++ b/src/pubkey/ec_dompar/ec_dompar.h @@ -1,5 +1,6 @@ /* -* ECDSA Domain Parameters +* ECC Domain Parameters +* * (C) 2007 Falko Strenzke, FlexSecure GmbH * 2008 Jack Lloyd * diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index 615efecf1..677a5088e 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -10,7 +10,6 @@ #include <botan/ecc_key.h> #include <botan/x509_key.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index 9640c6397..ea2c35a19 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -9,7 +9,6 @@ #include <botan/ecdsa.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/eckaeg/eckaeg.cpp b/src/pubkey/eckaeg/eckaeg.cpp index b8ff75d89..dc6eb925b 100644 --- a/src/pubkey/eckaeg/eckaeg.cpp +++ b/src/pubkey/eckaeg/eckaeg.cpp @@ -9,7 +9,6 @@ #include <botan/eckaeg.h> #include <botan/numthry.h> -#include <botan/util.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/secmem.h> diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp index 1f79df57a..8c07c5735 100644 --- a/src/pubkey/elgamal/elgamal.cpp +++ b/src/pubkey/elgamal/elgamal.cpp @@ -9,7 +9,7 @@ #include <botan/numthry.h> #include <botan/keypair.h> #include <botan/look_pk.h> -#include <botan/util.h> +#include <botan/workfactor.h> namespace Botan { diff --git a/src/pubkey/info.txt b/src/pubkey/info.txt index ee8da5b9d..63af86c47 100644 --- a/src/pubkey/info.txt +++ b/src/pubkey/info.txt @@ -15,6 +15,8 @@ pubkey.cpp pubkey.h pubkey_enums.cpp pubkey_enums.h +workfactor.cpp +workfactor.h </add> <requires> diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index f07533a4f..0580fe8eb 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -28,7 +28,13 @@ class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, SecureVector<byte> verify(const byte[], u32bit) const; RSA_PublicKey() {} - RSA_PublicKey(const BigInt&, const BigInt&); + + /** + * Create a RSA_PublicKey + * @arg n the modulus + * @arg e the exponent + */ + RSA_PublicKey(const BigInt& n, const BigInt& e); protected: BigInt public_op(const BigInt&) const; }; diff --git a/src/utils/util.cpp b/src/pubkey/workfactor.cpp index 84dfd1a14..e40b7919c 100644 --- a/src/utils/util.cpp +++ b/src/pubkey/workfactor.cpp @@ -1,35 +1,17 @@ /* -* Utility Functions +* Public Key Work Factor Functions * (C) 1999-2007 Jack Lloyd * * Distributed under the terms of the Botan license */ -#include <botan/util.h> +#include <botan/workfactor.h> #include <algorithm> #include <cmath> namespace Botan { /* -* Round up n to multiple of align_to -*/ -u32bit round_up(u32bit n, u32bit align_to) - { - if(n % align_to || n == 0) - n += align_to - (n % align_to); - return n; - } - -/* -* Round down n to multiple of align_to -*/ -u32bit round_down(u32bit n, u32bit align_to) - { - return (n - (n % align_to)); - } - -/* * Choose the exponent size for a DL group */ u32bit dl_work_factor(u32bit bits) @@ -65,4 +47,5 @@ u32bit dl_work_factor(u32bit bits) #endif } + } diff --git a/src/pubkey/workfactor.h b/src/pubkey/workfactor.h new file mode 100644 index 000000000..653f697e3 --- /dev/null +++ b/src/pubkey/workfactor.h @@ -0,0 +1,22 @@ +/* +* Public Key Work Factor Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_WORKFACTOR_H__ +#define BOTAN_WORKFACTOR_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Work Factor Estimates +*/ +BOTAN_DLL u32bit dl_work_factor(u32bit prime_group_size); + +} + +#endif diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp index 8405170ad..f02a9249f 100644 --- a/src/rng/auto_rng/auto_rng.cpp +++ b/src/rng/auto_rng/auto_rng.cpp @@ -143,7 +143,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) && defined(BOTAN_HAS_AES) diff --git a/src/rng/auto_rng/auto_rng.h b/src/rng/auto_rng/auto_rng.h index f18f8e5cd..a15b11b13 100644 --- a/src/rng/auto_rng/auto_rng.h +++ b/src/rng/auto_rng/auto_rng.h @@ -23,7 +23,7 @@ class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator { rng->randomize(out, len); } bool is_seeded() const { return rng->is_seeded(); } - void clear() throw() { rng->clear(); } + void clear() { rng->clear(); } std::string name() const { return "AutoSeeded(" + rng->name() + ")"; } diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp index 113489db3..9d5ee97e4 100644 --- a/src/rng/hmac_rng/hmac_rng.cpp +++ b/src/rng/hmac_rng/hmac_rng.cpp @@ -8,7 +8,6 @@ #include <botan/hmac_rng.h> #include <botan/loadstor.h> #include <botan/xor_buf.h> -#include <botan/util.h> #include <botan/stl_util.h> #include <algorithm> @@ -148,7 +147,7 @@ void HMAC_RNG::add_entropy_source(EntropySource* src) /* * Clear memory of sensitive data */ -void HMAC_RNG::clear() throw() +void HMAC_RNG::clear() { extractor->clear(); prf->clear(); diff --git a/src/rng/hmac_rng/hmac_rng.h b/src/rng/hmac_rng/hmac_rng.h index 318e2a931..97b0baf15 100644 --- a/src/rng/hmac_rng/hmac_rng.h +++ b/src/rng/hmac_rng/hmac_rng.h @@ -29,7 +29,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator public: void randomize(byte buf[], u32bit len); bool is_seeded() const { return seeded; } - void clear() throw(); + void clear(); std::string name() const; void reseed(u32bit poll_bits); diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp index 77a5228c6..9ec92267d 100644 --- a/src/rng/randpool/randpool.cpp +++ b/src/rng/randpool/randpool.cpp @@ -8,7 +8,7 @@ #include <botan/randpool.h> #include <botan/loadstor.h> #include <botan/xor_buf.h> -#include <botan/util.h> +#include <botan/timer.h> #include <botan/stl_util.h> #include <algorithm> @@ -149,7 +149,7 @@ void Randpool::add_entropy_source(EntropySource* src) /** * Clear memory of sensitive data */ -void Randpool::clear() throw() +void Randpool::clear() { cipher->clear(); mac->clear(); diff --git a/src/rng/randpool/randpool.h b/src/rng/randpool/randpool.h index b6a3adda4..ab6ed6748 100644 --- a/src/rng/randpool/randpool.h +++ b/src/rng/randpool/randpool.h @@ -23,7 +23,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator public: void randomize(byte[], u32bit); bool is_seeded() const { return seeded; } - void clear() throw(); + void clear(); std::string name() const; void reseed(u32bit bits_to_collect); diff --git a/src/rng/rng.h b/src/rng/rng.h index 41904dbef..c53d8e22d 100644 --- a/src/rng/rng.h +++ b/src/rng/rng.h @@ -47,7 +47,7 @@ class BOTAN_DLL RandomNumberGenerator /** * Clear all internally held values of this RNG. */ - virtual void clear() throw() = 0; + virtual void clear() = 0; /** * Return the name of this object @@ -89,7 +89,7 @@ class BOTAN_DLL Null_RNG : public RandomNumberGenerator { public: void randomize(byte[], u32bit) { throw PRNG_Unseeded("Null_RNG"); } - void clear() throw() {} + void clear() {} std::string name() const { return "Null_RNG"; } void reseed(u32bit) {} diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp index e239bce84..64d57ac1c 100644 --- a/src/rng/x931_rng/x931_rng.cpp +++ b/src/rng/x931_rng/x931_rng.cpp @@ -108,7 +108,7 @@ bool ANSI_X931_RNG::is_seeded() const /** * Clear memory of sensitive data */ -void ANSI_X931_RNG::clear() throw() +void ANSI_X931_RNG::clear() { cipher->clear(); prng->clear(); diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h index 44e9b4428..d5ba2e9eb 100644 --- a/src/rng/x931_rng/x931_rng.h +++ b/src/rng/x931_rng/x931_rng.h @@ -21,7 +21,7 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator public: void randomize(byte[], u32bit); bool is_seeded() const; - void clear() throw(); + void clear(); std::string name() const; void reseed(u32bit poll_bits); diff --git a/src/selftest/info.txt b/src/selftest/info.txt index 323a610a6..c4b61bb99 100644 --- a/src/selftest/info.txt +++ b/src/selftest/info.txt @@ -11,11 +11,6 @@ selftest.h <requires> algo_factory -cbc -cfb -ctr -ecb filters -hmac -ofb +def_engine </requires> diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index d644e866e..660be36e4 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -7,12 +7,8 @@ #include <botan/selftest.h> #include <botan/filters.h> -#include <botan/ecb.h> -#include <botan/cbc.h> -#include <botan/cfb.h> -#include <botan/ofb.h> -#include <botan/ctr.h> -#include <botan/hmac.h> +#include <botan/def_eng.h> +#include <botan/stl_util.h> namespace Botan { @@ -21,23 +17,143 @@ namespace { /* * Perform a Known Answer Test */ -void do_kat(const std::string& in, const std::string& out, - const std::string& algo_name, Filter* filter) +bool test_filter_kat(Filter* filter, + const std::string& input, + const std::string& output) { - if(out.length()) + Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); + pipe.process_msg(input); + + return (output == pipe.read_all_as_string()); + } + +} + +/* +* Run a set of KATs +*/ +std::map<std::string, bool> +algorithm_kat(const SCAN_Name& algo_name, + const std::map<std::string, std::string>& vars, + Algorithm_Factory& af) + { + const std::string& algo = algo_name.algo_name_and_args(); + + std::vector<std::string> providers = af.providers_of(algo); + std::map<std::string, bool> all_results; + + if(providers.empty()) // no providers, nothing to do + return all_results; + + const std::string input = search_map(vars, std::string("input")); + const std::string output = search_map(vars, std::string("output")); + const std::string key = search_map(vars, std::string("key")); + const std::string iv = search_map(vars, std::string("iv")); + + for(u32bit i = 0; i != providers.size(); ++i) { - Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); - pipe.process_msg(in); + const std::string provider = providers[i]; - if(out != pipe.read_all_as_string()) - throw Self_Test_Failure(algo_name + " startup test"); + if(const HashFunction* proto = + af.prototype_hash_function(algo, provider)) + { + Filter* filt = new Hash_Filter(proto->clone()); + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const MessageAuthenticationCode* proto = + af.prototype_mac(algo, provider)) + { + Keyed_Filter* filt = new MAC_Filter(proto->clone(), key); + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const StreamCipher* proto = + af.prototype_stream_cipher(algo, provider)) + { + Keyed_Filter* filt = new StreamCipher_Filter(proto->clone()); + filt->set_key(key); + filt->set_iv(iv); + + all_results[provider] = test_filter_kat(filt, input, output); + } + else if(const BlockCipher* proto = + af.prototype_block_cipher(algo, provider)) + { + Keyed_Filter* enc = get_cipher_mode(proto, ENCRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + Keyed_Filter* dec = get_cipher_mode(proto, DECRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + if(!enc || !dec) + { + delete enc; + delete dec; + continue; + } + + enc->set_key(key); + enc->set_iv(iv); + + dec->set_key(key); + dec->set_iv(iv); + + bool enc_ok = test_filter_kat(enc, input, output); + bool dec_ok = test_filter_kat(dec, output, input); + + all_results[provider] = enc_ok && dec_ok; + } } + + return all_results; + } + +namespace { + +void verify_results(const std::string& algo, + const std::map<std::string, bool>& results) + { + for(std::map<std::string, bool>::const_iterator i = results.begin(); + i != results.end(); ++i) + { + if(!i->second) + throw Self_Test_Failure(algo + " self-test failed, provider "+ + i->first); + } + } + +void hash_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + + verify_results(name, algorithm_kat(name, vars, af)); + } + +void mac_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out, + const std::string& key) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + vars["key"] = key; + + verify_results(name, algorithm_kat(name, vars, af)); } /* * Perform a KAT for a cipher */ -void cipher_kat(const BlockCipher* proto, +void cipher_kat(Algorithm_Factory& af, + const std::string& algo, const std::string& key_str, const std::string& iv_str, const std::string& in, @@ -50,27 +166,28 @@ void cipher_kat(const BlockCipher* proto, SymmetricKey key(key_str); InitializationVector iv(iv_str); - std::string name = proto->name(); + std::map<std::string, std::string> vars; + vars["key"] = key_str; + vars["iv"] = iv_str; + vars["input"] = in; + + std::map<std::string, bool> results; - do_kat(in, ecb_out, name + "/ECB", - new ECB_Encryption(proto->clone(), new Null_Padding, key)); - do_kat(ecb_out, in, name + "/ECB", - new ECB_Decryption(proto->clone(), new Null_Padding, key)); + vars["output"] = ecb_out; + verify_results(algo + "/ECB", algorithm_kat(algo + "/ECB", vars, af)); - do_kat(in, cbc_out, name + "/CBC", - new CBC_Encryption(proto->clone(), new Null_Padding, key, iv)); - do_kat(cbc_out, in, name + "/CBC", - new CBC_Decryption(proto->clone(), new Null_Padding, key, iv)); + vars["output"] = cbc_out; + verify_results(algo + "/CBC", + algorithm_kat(algo + "/CBC/NoPadding", vars, af)); - do_kat(in, cfb_out, name + "/CFB", - new CFB_Encryption(proto->clone(), key, iv)); - do_kat(cfb_out, in, name + "/CFB", - new CFB_Decryption(proto->clone(), key, iv)); + vars["output"] = cfb_out; + verify_results(algo + "/CFB", algorithm_kat(algo + "/CFB", vars, af)); - do_kat(in, ofb_out, name + "/OFB", new OFB(proto->clone(), key, iv)); + vars["output"] = ofb_out; + verify_results(algo + "/OFB", algorithm_kat(algo + "/OFB", vars, af)); - do_kat(in, ctr_out, name + "/CTR-BE", - new CTR_BE(proto->clone(), key, iv)); + vars["output"] = ctr_out; + verify_results(algo + "/CTR", algorithm_kat(algo + "/CTR-BE", vars, af)); } } @@ -82,9 +199,7 @@ bool passes_self_tests(Algorithm_Factory& af) { try { - if(const BlockCipher* proto = af.prototype_block_cipher("DES")) - { - cipher_kat(proto, + cipher_kat(af, "DES", "0123456789ABCDEF", "1234567890ABCDEF", "4E6F77206973207468652074696D6520666F7220616C6C20", "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53", @@ -92,11 +207,8 @@ bool passes_self_tests(Algorithm_Factory& af) "F3096249C7F46E51A69E839B1A92F78403467133898EA622", "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3", "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75"); - } - if(const BlockCipher* proto = af.prototype_block_cipher("TripleDES")) - { - cipher_kat(proto, + cipher_kat(af, "TripleDES", "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E", "C141B5FCCD28DC8A", "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68", @@ -105,75 +217,63 @@ bool passes_self_tests(Algorithm_Factory& af) "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B", "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62", "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371"); - } - - if(const BlockCipher* proto = af.prototype_block_cipher("AES")) - { - cipher_kat(proto, - "2B7E151628AED2A6ABF7158809CF4F3C", - "000102030405060708090A0B0C0D0E0F", - "6BC1BEE22E409F96E93D7E117393172A" - "AE2D8A571E03AC9C9EB76FAC45AF8E51", - "3AD77BB40D7A3660A89ECAF32466EF97" - "F5D3D58503B9699DE785895A96FDBAAF", - "7649ABAC8119B246CEE98E9B12E9197D" - "5086CB9B507219EE95DB113A917678B2", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "C8A64537A0B3A93FCDE3CDAD9F1CE58B", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "7789508D16918F03F53C52DAC54ED825", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "010C041999E03F36448624483E582D0E"); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-1")) - { - do_kat("", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", "A9993E364706816ABA3E25717850C26C9CD0D89D", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + + cipher_kat(af, "AES-128", + "2B7E151628AED2A6ABF7158809CF4F3C", + "000102030405060708090A0B0C0D0E0F", + "6BC1BEE22E409F96E93D7E117393172A" + "AE2D8A571E03AC9C9EB76FAC45AF8E51", + "3AD77BB40D7A3660A89ECAF32466EF97" + "F5D3D58503B9699DE785895A96FDBAAF", + "7649ABAC8119B246CEE98E9B12E9197D" + "5086CB9B507219EE95DB113A917678B2", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "C8A64537A0B3A93FCDE3CDAD9F1CE58B", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "7789508D16918F03F53C52DAC54ED825", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "010C041999E03F36448624483E582D0E"); + + hash_test(af, "SHA-1", + "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + + hash_test(af, "SHA-1", + "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D"); + + hash_test(af, "SHA-1", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", - "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "B617318655057264E28BC0B6FB378C8EF146BE00", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-256")) - { - do_kat("", - "E3B0C44298FC1C149AFBF4C8996FB924" - "27AE41E4649B934CA495991B7852B855", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", - "BA7816BF8F01CFEA414140DE5DAE2223" - "B00361A396177A9CB410FF61F20015AD", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); + + mac_test(af, "HMAC(SHA-1)", + "4869205468657265", + "B617318655057264E28BC0B6FB378C8EF146BE00", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); + + hash_test(af, "SHA-256", + "", + "E3B0C44298FC1C149AFBF4C8996FB924" + "27AE41E4649B934CA495991B7852B855"); + + hash_test(af, "SHA-256", + "616263", + "BA7816BF8F01CFEA414140DE5DAE2223" + "B00361A396177A9CB410FF61F20015AD"); + + hash_test(af, "SHA-256", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", "248D6A61D20638B8E5C026930C3E6039" - "A33CE45964FF2167F6ECEDD419DB06C1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "198A607EB44BFBC69903A0F1CF2BBDC5" - "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } + "A33CE45964FF2167F6ECEDD419DB06C1"); + + mac_test(af, "HMAC(SHA-256)", + "4869205468657265", + "198A607EB44BFBC69903A0F1CF2BBDC5" + "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); } - catch(std::exception) + catch(Self_Test_Failure) { return false; } diff --git a/src/selftest/selftest.h b/src/selftest/selftest.h index 9e36d2298..4cb6e23d7 100644 --- a/src/selftest/selftest.h +++ b/src/selftest/selftest.h @@ -9,6 +9,9 @@ #define BOTAN_SELF_TESTS_H__ #include <botan/algo_factory.h> +#include <botan/scan_name.h> +#include <map> +#include <string> namespace Botan { @@ -17,6 +20,11 @@ namespace Botan { */ BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af); +BOTAN_DLL std::map<std::string, bool> +algorithm_kat(const SCAN_Name& algo_name, + const std::map<std::string, std::string>& vars, + Algorithm_Factory& af); + } #endif diff --git a/src/stream/arc4/arc4.cpp b/src/stream/arc4/arc4.cpp index 0f78f7362..293a0a336 100644 --- a/src/stream/arc4/arc4.cpp +++ b/src/stream/arc4/arc4.cpp @@ -87,7 +87,7 @@ std::string ARC4::name() const /* * Clear memory of sensitive data */ -void ARC4::clear() throw() +void ARC4::clear() { state.clear(); buffer.clear(); diff --git a/src/stream/arc4/arc4.h b/src/stream/arc4/arc4.h index aa2cea7fe..ae37cb165 100644 --- a/src/stream/arc4/arc4.h +++ b/src/stream/arc4/arc4.h @@ -19,13 +19,16 @@ namespace Botan { class BOTAN_DLL ARC4 : public StreamCipher { public: - void clear() throw(); + void cipher(const byte in[], byte out[], u32bit length); + + void clear(); std::string name() const; + StreamCipher* clone() const { return new ARC4(SKIP); } + ARC4(u32bit = 0); ~ARC4() { clear(); } private: - void cipher(const byte[], byte[], u32bit); void key_schedule(const byte[], u32bit); void generate(); diff --git a/src/stream/ctr/ctr.cpp b/src/stream/ctr/ctr.cpp new file mode 100644 index 000000000..5f0880fa5 --- /dev/null +++ b/src/stream/ctr/ctr.cpp @@ -0,0 +1,141 @@ +/* +* CTR-BE Mode Cipher +* (C) 1999-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/ctr.h> +#include <botan/xor_buf.h> + +namespace Botan { + +/* +* CTR-BE Constructor +*/ + +CTR_BE::CTR_BE(BlockCipher* ciph) : + StreamCipher(ciph->MINIMUM_KEYLENGTH, + ciph->MAXIMUM_KEYLENGTH, + ciph->KEYLENGTH_MULTIPLE), + permutation(ciph) + { + position = 0; + + counter.create(permutation->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_CTR); + buffer.create(permutation->BLOCK_SIZE * BOTAN_PARALLEL_BLOCKS_CTR); + } + +/* +* CTR_BE Destructor +*/ +CTR_BE::~CTR_BE() + { + delete permutation; + } + +/* +* Zeroize +*/ +void CTR_BE::clear() + { + permutation->clear(); + buffer.clear(); + counter.clear(); + position = 0; + } + +/* +* Set the key +*/ +void CTR_BE::key_schedule(const byte key[], u32bit key_len) + { + permutation->set_key(key, key_len); + + // Set a default all-zeros IV + set_iv(0, 0); + } + +/* +* Return the name of this type +*/ +std::string CTR_BE::name() const + { + return ("CTR-BE(" + permutation->name() + ")"); + } + +/* +* CTR-BE Encryption/Decryption +*/ +void CTR_BE::cipher(const byte in[], byte out[], u32bit length) + { + while(length >= buffer.size() - position) + { + xor_buf(out, in, buffer.begin() + position, buffer.size() - position); + length -= (buffer.size() - position); + in += (buffer.size() - position); + out += (buffer.size() - position); + increment_counter(); + } + xor_buf(out, in, buffer.begin() + position, length); + position += length; + } + +/* +* Set CTR-BE IV +*/ +void CTR_BE::set_iv(const byte iv[], u32bit iv_len) + { + if(!valid_iv_length(iv_len)) + throw Invalid_IV_Length(name(), iv_len); + + const u32bit BLOCK_SIZE = permutation->BLOCK_SIZE; + + counter.clear(); + + counter.copy(0, iv, iv_len); + + const u32bit PARALLEL_BLOCKS = counter.size() / BLOCK_SIZE; + + 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; + } + + permutation->encrypt_n(counter, buffer, PARALLEL_BLOCKS); + position = 0; + } + +/* +* Increment the counter and update the buffer +*/ +void CTR_BE::increment_counter() + { + const u32bit PARALLEL_BLOCKS = counter.size() / permutation->BLOCK_SIZE; + + for(u32bit i = 0; i != PARALLEL_BLOCKS; ++i) + { + byte* this_ctr = counter + i*permutation->BLOCK_SIZE; + + byte last_byte = this_ctr[permutation->BLOCK_SIZE-1]; + last_byte += PARALLEL_BLOCKS; + + if(this_ctr[permutation->BLOCK_SIZE-1] > last_byte) + for(s32bit j = permutation->BLOCK_SIZE - 2; j >= 0; --j) + if(++this_ctr[j]) + break; + + this_ctr[permutation->BLOCK_SIZE-1] = last_byte; + } + + permutation->encrypt_n(counter, buffer, PARALLEL_BLOCKS); + + position = 0; + } + +} diff --git a/src/stream/ctr/ctr.h b/src/stream/ctr/ctr.h new file mode 100644 index 000000000..5f94170cc --- /dev/null +++ b/src/stream/ctr/ctr.h @@ -0,0 +1,49 @@ +/* +* CTR-BE Mode +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CTR_BE_H__ +#define BOTAN_CTR_BE_H__ + +#include <botan/block_cipher.h> +#include <botan/stream_cipher.h> + +namespace Botan { + +/* +* CTR-BE (Counter, big-endian) +*/ +class BOTAN_DLL CTR_BE : public StreamCipher + { + public: + void cipher(const byte in[], byte out[], u32bit length); + + void set_iv(const byte iv[], u32bit iv_len); + + bool valid_iv_length(u32bit iv_len) const + { return (iv_len <= permutation->BLOCK_SIZE); } + + std::string name() const; + + CTR_BE* clone() const + { return new CTR_BE(permutation->clone()); } + + void clear(); + + CTR_BE(BlockCipher*); + ~CTR_BE(); + private: + void key_schedule(const byte key[], u32bit key_len); + void increment_counter(); + + BlockCipher* permutation; + SecureVector<byte> counter, buffer; + u32bit position; + }; + +} + +#endif diff --git a/src/modes/ctr/info.txt b/src/stream/ctr/info.txt index cb291a2c1..04d14518a 100644 --- a/src/modes/ctr/info.txt +++ b/src/stream/ctr/info.txt @@ -1,6 +1,6 @@ -realname "CTR block cipher mode" +realname "CTR mode" -define CTR +define CTR_BE load_on auto @@ -10,6 +10,7 @@ ctr.h </add> <requires> -modes +block +stream </requires> diff --git a/src/stream/info.txt b/src/stream/info.txt index 295c73708..f8f4b22d5 100644 --- a/src/stream/info.txt +++ b/src/stream/info.txt @@ -6,7 +6,6 @@ define STREAM_CIPHER <add> stream_cipher.h -stream_cipher.cpp </add> <requires> diff --git a/src/modes/ofb/info.txt b/src/stream/ofb/info.txt index 3cba4151e..444fe0ffe 100644 --- a/src/modes/ofb/info.txt +++ b/src/stream/ofb/info.txt @@ -11,4 +11,5 @@ ofb.h <requires> block +stream </requires> diff --git a/src/stream/ofb/ofb.cpp b/src/stream/ofb/ofb.cpp new file mode 100644 index 000000000..0d12d23bd --- /dev/null +++ b/src/stream/ofb/ofb.cpp @@ -0,0 +1,97 @@ +/* +* OFB Mode +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/ofb.h> +#include <botan/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/* +* OFB Constructor +*/ +OFB::OFB(BlockCipher* ciph) : + StreamCipher(ciph->MINIMUM_KEYLENGTH, + ciph->MAXIMUM_KEYLENGTH, + ciph->KEYLENGTH_MULTIPLE), + permutation(ciph) + { + position = 0; + buffer.create(permutation->BLOCK_SIZE); + } + +/* +* OFB Destructor +*/ +OFB::~OFB() + { + delete permutation; + } + +/* +* Zeroize +*/ +void OFB::clear() + { + permutation->clear(); + buffer.clear(); + position = 0; + } + +/* +* Set the key +*/ +void OFB::key_schedule(const byte key[], u32bit key_len) + { + permutation->set_key(key, key_len); + + // Set a default all-zeros IV + set_iv(0, 0); + } + +/* +* Return the name of this type +*/ +std::string OFB::name() const + { + return ("OFB(" + permutation->name() + ")"); + } + +/* +* CTR-BE Encryption/Decryption +*/ +void OFB::cipher(const byte in[], byte out[], u32bit length) + { + while(length >= buffer.size() - position) + { + xor_buf(out, in, buffer.begin() + position, buffer.size() - position); + length -= (buffer.size() - position); + in += (buffer.size() - position); + out += (buffer.size() - position); + permutation->encrypt(buffer); + position = 0; + } + xor_buf(out, in, buffer.begin() + position, length); + position += length; + } + +/* +* Set CTR-BE IV +*/ +void OFB::set_iv(const byte iv[], u32bit iv_len) + { + if(!valid_iv_length(iv_len)) + throw Invalid_IV_Length(name(), iv_len); + + buffer.clear(); + buffer.copy(0, iv, iv_len); + + permutation->encrypt(buffer); + position = 0; + } + +} diff --git a/src/stream/ofb/ofb.h b/src/stream/ofb/ofb.h new file mode 100644 index 000000000..1985ae5a9 --- /dev/null +++ b/src/stream/ofb/ofb.h @@ -0,0 +1,48 @@ +/* +* OFB Mode +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_OUTPUT_FEEDBACK_MODE_H__ +#define BOTAN_OUTPUT_FEEDBACK_MODE_H__ + +#include <botan/stream_cipher.h> +#include <botan/block_cipher.h> + +namespace Botan { + +/* +* OFB Mode +*/ +class BOTAN_DLL OFB : public StreamCipher + { + public: + void cipher(const byte in[], byte out[], u32bit length); + + void set_iv(const byte iv[], u32bit iv_len); + + bool valid_iv_length(u32bit iv_len) const + { return (iv_len <= permutation->BLOCK_SIZE); } + + std::string name() const; + + OFB* clone() const + { return new OFB(permutation->clone()); } + + void clear(); + + OFB(BlockCipher*); + ~OFB(); + private: + void key_schedule(const byte key[], u32bit key_len); + + BlockCipher* permutation; + SecureVector<byte> buffer; + u32bit position; + }; + +} + +#endif diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp index 75137798c..3aae64eae 100644 --- a/src/stream/salsa20/salsa20.cpp +++ b/src/stream/salsa20/salsa20.cpp @@ -6,10 +6,8 @@ */ #include <botan/salsa20.h> -#include <botan/mem_ops.h> #include <botan/xor_buf.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { @@ -164,15 +162,15 @@ void Salsa20::key_schedule(const byte key[], u32bit length) } const byte ZERO[8] = { 0 }; - resync(ZERO, sizeof(ZERO)); + set_iv(ZERO, sizeof(ZERO)); } /* * Return the name of this type */ -void Salsa20::resync(const byte iv[], u32bit length) +void Salsa20::set_iv(const byte iv[], u32bit length) { - if(length != IV_LENGTH) + if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); state[6] = load_le<u32bit>(iv, 0); @@ -199,7 +197,7 @@ std::string Salsa20::name() const /* * Clear memory of sensitive data */ -void Salsa20::clear() throw() +void Salsa20::clear() { state.clear(); buffer.clear(); @@ -209,7 +207,7 @@ void Salsa20::clear() throw() /* * Salsa20 Constructor */ -Salsa20::Salsa20() : StreamCipher(16, 32, 16, 8) +Salsa20::Salsa20() : StreamCipher(16, 32, 16) { clear(); } diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h index 3dbfddb50..3ca781ea2 100644 --- a/src/stream/salsa20/salsa20.h +++ b/src/stream/salsa20/salsa20.h @@ -18,17 +18,21 @@ namespace Botan { class BOTAN_DLL Salsa20 : public StreamCipher { public: - void clear() throw(); + void cipher(const byte in[], byte out[], u32bit length); + + void set_iv(const byte iv[], u32bit iv_len); + + bool valid_iv_length(u32bit iv_len) const + { return (iv_len == 8); } + + void clear(); std::string name() const; StreamCipher* clone() const { return new Salsa20; } - void resync(const byte[], u32bit); - Salsa20(); ~Salsa20() { clear(); } private: - void cipher(const byte[], byte[], u32bit); - void key_schedule(const byte[], u32bit); + void key_schedule(const byte key[], u32bit key_len); SecureBuffer<u32bit, 16> state; diff --git a/src/stream/stream_cipher.cpp b/src/stream/stream_cipher.cpp deleted file mode 100644 index 68bb5d4f0..000000000 --- a/src/stream/stream_cipher.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/** -* Stream Cipher Default Implementation for IV and Seek -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/stream_cipher.h> - -namespace Botan { - -/* -* Default StreamCipher Resync Operation -*/ -void StreamCipher::resync(const byte[], u32bit length) - { - if(length) - throw Exception("The stream cipher " + name() + - " does not support resyncronization"); - } - -/* -* Default StreamCipher Seek Operation -*/ -void StreamCipher::seek(u32bit) - { - throw Exception("The stream cipher " + name() + " does not support seek()"); - } - -} diff --git a/src/stream/stream_cipher.h b/src/stream/stream_cipher.h index 8ea359131..29c16c8b5 100644 --- a/src/stream/stream_cipher.h +++ b/src/stream/stream_cipher.h @@ -18,53 +18,40 @@ namespace Botan { class BOTAN_DLL StreamCipher : public SymmetricAlgorithm { public: - const u32bit IV_LENGTH; - - /** - * Encrypt a message. - * @param i the plaintext - * @param o the byte array to hold the output, i.e. the ciphertext - * @param len the length of both i and o - */ - void encrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); } - /** - * Decrypt a message. - * @param i the ciphertext to decrypt - * @param o the byte array to hold the output, i.e. the plaintext - * @param len the length of both i and o + * Encrypt or decrypt a message + * @param in the plaintext + * @param out the byte array to hold the output, i.e. the ciphertext + * @param len the length of both in and out in bytes */ - void decrypt(const byte i[], byte o[], u32bit len) { cipher(i, o, len); } + virtual void cipher(const byte in[], byte out[], u32bit len) = 0; /** - * Encrypt a message. - * @param in the plaintext as input, after the function has - * returned it will hold the ciphertext - - * @param len the length of in + * Encrypt or decrypt a message + * @param buf the plaintext / ciphertext + * @param len the length of buf in bytes */ - void encrypt(byte in[], u32bit len) { cipher(in, in, len); } - - /** - * Decrypt a message. - * @param in the ciphertext as input, after the function has - * returned it will hold the plaintext - * @param len the length of in - */ - void decrypt(byte in[], u32bit len) { cipher(in, in, len); } + void cipher1(byte buf[], u32bit len) + { cipher(buf, buf, len); } /** * Resync the cipher using the IV * @param iv the initialization vector * @param iv_len the length of the IV in bytes */ - virtual void resync(const byte iv[], u32bit iv_len); + virtual void set_iv(const byte[], u32bit iv_len) + { + if(iv_len) + throw Exception("The stream cipher " + name() + + " does not support resyncronization"); + } /** - * Seek ahead in the stream. - * @param len the length to seek ahead. + * @param iv_len the length of the IV in bytes + * @return if the length is valid for this algorithm */ - virtual void seek(u32bit len); + virtual bool valid_iv_length(u32bit iv_len) const + { return (iv_len == 0); } /** * Get a new object representing the same algorithm as *this @@ -74,17 +61,17 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm /** * Zeroize internal state */ - virtual void clear() throw() = 0; + virtual void clear() = 0; - StreamCipher(u32bit key_min, u32bit key_max = 0, - u32bit key_mod = 1, - u32bit iv_len = 0) : - SymmetricAlgorithm(key_min, key_max, key_mod), - IV_LENGTH(iv_len) {} + /** + * StreamCipher constructor + */ + StreamCipher(u32bit key_min, + u32bit key_max = 0, + u32bit key_mod = 1) : + SymmetricAlgorithm(key_min, key_max, key_mod) {} virtual ~StreamCipher() {} - private: - virtual void cipher(const byte[], byte[], u32bit) = 0; }; } diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp index b988568c3..810f65ca4 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,20 +231,41 @@ 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); + set_iv(0, 0); } /* * Resynchronization */ -void Turing::resync(const byte iv[], u32bit length) +void Turing::set_iv(const byte iv[], u32bit length) { - if(length % 4 != 0 || length > 16) + if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); SecureVector<u32bit> IV(length / 4); @@ -293,7 +295,7 @@ void Turing::resync(const byte iv[], u32bit length) /* * Clear memory of sensitive data */ -void Turing::clear() throw() +void Turing::clear() { S0.clear(); S1.clear(); diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h index d48c1d8a8..7291647ea 100644 --- a/src/stream/turing/turing.h +++ b/src/stream/turing/turing.h @@ -18,19 +18,21 @@ namespace Botan { class BOTAN_DLL Turing : public StreamCipher { public: - void clear() throw(); + void cipher(const byte in[], byte out[], u32bit length); + void set_iv(const byte[], u32bit); + + bool valid_iv_length(u32bit iv_len) const + { return (iv_len % 4 == 0 && iv_len <= 16); } + + void clear(); std::string name() const { return "Turing"; } StreamCipher* clone() const { return new Turing; } Turing() : StreamCipher(4, 32, 4) { position = 0; } private: - void cipher(const byte[], byte[], u32bit); void key_schedule(const byte[], u32bit); - void resync(const byte[], u32bit); 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]; diff --git a/src/stream/wid_wake/wid_wake.cpp b/src/stream/wid_wake/wid_wake.cpp index 1dc0fd7f9..2a8946649 100644 --- a/src/stream/wid_wake/wid_wake.cpp +++ b/src/stream/wid_wake/wid_wake.cpp @@ -110,16 +110,17 @@ void WiderWake_41_BE::key_schedule(const byte key[], u32bit) T[X] = Z; position = 0; - const byte iv[8] = { 0 }; - resync(iv, 8); + + const byte ZEROS[8] = { 0 }; + set_iv(ZEROS, sizeof(ZEROS)); } /* * Resynchronization */ -void WiderWake_41_BE::resync(const byte iv[], u32bit length) +void WiderWake_41_BE::set_iv(const byte iv[], u32bit length) { - if(length != 8) + if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); for(u32bit j = 0; j != 4; ++j) @@ -135,7 +136,7 @@ void WiderWake_41_BE::resync(const byte iv[], u32bit length) /* * Clear memory of sensitive data */ -void WiderWake_41_BE::clear() throw() +void WiderWake_41_BE::clear() { position = 0; t_key.clear(); diff --git a/src/stream/wid_wake/wid_wake.h b/src/stream/wid_wake/wid_wake.h index 4720afdb2..23e1eacab 100644 --- a/src/stream/wid_wake/wid_wake.h +++ b/src/stream/wid_wake/wid_wake.h @@ -18,14 +18,18 @@ namespace Botan { class BOTAN_DLL WiderWake_41_BE : public StreamCipher { public: - void clear() throw(); + void cipher(const byte[], byte[], u32bit); + void set_iv(const byte[], u32bit); + + bool valid_iv_length(u32bit iv_len) const + { return (iv_len == 8); } + + void clear(); std::string name() const { return "WiderWake4+1-BE"; } StreamCipher* clone() const { return new WiderWake_41_BE; } - WiderWake_41_BE() : StreamCipher(16, 16, 1, 8) {} + WiderWake_41_BE() : StreamCipher(16, 16, 1) {} private: - void cipher(const byte[], byte[], u32bit); void key_schedule(const byte[], u32bit); - void resync(const byte[], u32bit); void generate(u32bit); diff --git a/src/sym_algo/sym_algo.h b/src/sym_algo/sym_algo.h index 1c8b816fd..929f2a6f0 100644 --- a/src/sym_algo/sym_algo.h +++ b/src/sym_algo/sym_algo.h @@ -46,7 +46,7 @@ class BOTAN_DLL SymmetricAlgorithm * Set the symmetric key of this object. * @param key the SymmetricKey to be set. */ - void set_key(const SymmetricKey& key) throw(Invalid_Key_Length) + void set_key(const SymmetricKey& key) { set_key(key.begin(), key.length()); } /** @@ -54,7 +54,7 @@ class BOTAN_DLL SymmetricAlgorithm * @param key the to be set as a byte array. * @param the length of the byte array. */ - void set_key(const byte key[], u32bit length) throw(Invalid_Key_Length) + void set_key(const byte key[], u32bit length) { if(!valid_keylength(length)) throw Invalid_Key_Length(name(), length); diff --git a/src/timer/gettimeofday/tm_unix.cpp b/src/timer/gettimeofday/tm_unix.cpp index e32df7166..9d8ac4a04 100644 --- a/src/timer/gettimeofday/tm_unix.cpp +++ b/src/timer/gettimeofday/tm_unix.cpp @@ -6,7 +6,6 @@ */ #include <botan/tm_unix.h> -#include <botan/util.h> #include <sys/time.h> namespace Botan { diff --git a/src/timer/posix_rt/tm_posix.cpp b/src/timer/posix_rt/tm_posix.cpp index d356384ab..96182025c 100644 --- a/src/timer/posix_rt/tm_posix.cpp +++ b/src/timer/posix_rt/tm_posix.cpp @@ -6,7 +6,6 @@ */ #include <botan/tm_posix.h> -#include <botan/util.h> #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309 diff --git a/src/timer/timer.cpp b/src/timer/timer.cpp index 035c217f9..16d7dc368 100644 --- a/src/timer/timer.cpp +++ b/src/timer/timer.cpp @@ -7,7 +7,6 @@ #include <botan/timer.h> #include <botan/loadstor.h> -#include <botan/util.h> #include <ctime> namespace Botan { @@ -20,6 +19,19 @@ u64bit system_time() return static_cast<u64bit>(std::time(0)); } +/* +* Convert a time_t to a struct tm +*/ +std::tm time_t_to_tm(u64bit timer) + { + std::time_t time_val = static_cast<std::time_t>(timer); + + std::tm* tm_p = std::gmtime(&time_val); + if (tm_p == 0) + throw Encoding_Error("time_t_to_tm could not convert"); + return (*tm_p); + } + /** * Read the clock and return the output */ diff --git a/src/timer/timer.h b/src/timer/timer.h index b6e8ef448..603027f6d 100644 --- a/src/timer/timer.h +++ b/src/timer/timer.h @@ -9,9 +9,17 @@ #define BOTAN_TIMERS_H__ #include <botan/rng.h> +#include <ctime> namespace Botan { +/* +* Time Access/Conversion Functions +*/ +BOTAN_DLL u64bit system_time(); + +BOTAN_DLL std::tm time_t_to_tm(u64bit); + /** * Timer Interface */ diff --git a/src/tss/info.txt b/src/tss/info.txt new file mode 100644 index 000000000..af4e0b930 --- /dev/null +++ b/src/tss/info.txt @@ -0,0 +1,8 @@ +realname "Threshold Secret Sharing" + +<requires> +hash +rng +filters +hex +</requires> diff --git a/src/tss/tss.cpp b/src/tss/tss.cpp new file mode 100644 index 000000000..3bd799727 --- /dev/null +++ b/src/tss/tss.cpp @@ -0,0 +1,263 @@ +/* +* RTSS (threshold secret sharing) +* (C) 2009 Jack Lloyd <[email protected]> +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/tss.h> +#include <botan/loadstor.h> +#include <botan/pipe.h> +#include <botan/hex.h> +#include <botan/sha2_32.h> +#include <botan/sha160.h> +#include <memory> + +namespace Botan { + +namespace { + +/** +Table for GF(2^8) arithmetic (exponentials) +*/ +const byte EXP[256] = { +0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, +0x96, 0xA1, 0xF8, 0x13, 0x35, 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, +0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA, 0xE5, +0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, +0x90, 0xAB, 0xE6, 0x31, 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, +0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD, 0x4C, 0xD4, +0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, +0x28, 0x78, 0x88, 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, +0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A, 0xB5, 0xC4, 0x57, +0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, +0x61, 0xA3, 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, +0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0, 0xFB, 0x16, 0x3A, 0x4E, +0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, +0x41, 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, +0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75, 0x9F, 0xBA, 0xD5, 0x64, 0xAC, +0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80, +0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, +0xB1, 0xC8, 0x43, 0xC5, 0x54, 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, +0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA, 0x45, +0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, +0xC6, 0x51, 0xF3, 0x0E, 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, +0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17, 0x39, 0x4B, +0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, +0x52, 0xF6, 0x01 }; + +/** +Table for GF(2^8) arithmetic (logarithms) +*/ +const byte LOG[] = { +0x90, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1A, 0xC6, 0x4B, 0xC7, 0x1B, +0x68, 0x33, 0xEE, 0xDF, 0x03, 0x64, 0x04, 0xE0, 0x0E, 0x34, 0x8D, +0x81, 0xEF, 0x4C, 0x71, 0x08, 0xC8, 0xF8, 0x69, 0x1C, 0xC1, 0x7D, +0xC2, 0x1D, 0xB5, 0xF9, 0xB9, 0x27, 0x6A, 0x4D, 0xE4, 0xA6, 0x72, +0x9A, 0xC9, 0x09, 0x78, 0x65, 0x2F, 0x8A, 0x05, 0x21, 0x0F, 0xE1, +0x24, 0x12, 0xF0, 0x82, 0x45, 0x35, 0x93, 0xDA, 0x8E, 0x96, 0x8F, +0xDB, 0xBD, 0x36, 0xD0, 0xCE, 0x94, 0x13, 0x5C, 0xD2, 0xF1, 0x40, +0x46, 0x83, 0x38, 0x66, 0xDD, 0xFD, 0x30, 0xBF, 0x06, 0x8B, 0x62, +0xB3, 0x25, 0xE2, 0x98, 0x22, 0x88, 0x91, 0x10, 0x7E, 0x6E, 0x48, +0xC3, 0xA3, 0xB6, 0x1E, 0x42, 0x3A, 0x6B, 0x28, 0x54, 0xFA, 0x85, +0x3D, 0xBA, 0x2B, 0x79, 0x0A, 0x15, 0x9B, 0x9F, 0x5E, 0xCA, 0x4E, +0xD4, 0xAC, 0xE5, 0xF3, 0x73, 0xA7, 0x57, 0xAF, 0x58, 0xA8, 0x50, +0xF4, 0xEA, 0xD6, 0x74, 0x4F, 0xAE, 0xE9, 0xD5, 0xE7, 0xE6, 0xAD, +0xE8, 0x2C, 0xD7, 0x75, 0x7A, 0xEB, 0x16, 0x0B, 0xF5, 0x59, 0xCB, +0x5F, 0xB0, 0x9C, 0xA9, 0x51, 0xA0, 0x7F, 0x0C, 0xF6, 0x6F, 0x17, +0xC4, 0x49, 0xEC, 0xD8, 0x43, 0x1F, 0x2D, 0xA4, 0x76, 0x7B, 0xB7, +0xCC, 0xBB, 0x3E, 0x5A, 0xFB, 0x60, 0xB1, 0x86, 0x3B, 0x52, 0xA1, +0x6C, 0xAA, 0x55, 0x29, 0x9D, 0x97, 0xB2, 0x87, 0x90, 0x61, 0xBE, +0xDC, 0xFC, 0xBC, 0x95, 0xCF, 0xCD, 0x37, 0x3F, 0x5B, 0xD1, 0x53, +0x39, 0x84, 0x3C, 0x41, 0xA2, 0x6D, 0x47, 0x14, 0x2A, 0x9E, 0x5D, +0x56, 0xF2, 0xD3, 0xAB, 0x44, 0x11, 0x92, 0xD9, 0x23, 0x20, 0x2E, +0x89, 0xB4, 0x7C, 0xB8, 0x26, 0x77, 0x99, 0xE3, 0xA5, 0x67, 0x4A, +0xED, 0xDE, 0xC5, 0x31, 0xFE, 0x18, 0x0D, 0x63, 0x8C, 0x80, 0xC0, +0xF7, 0x70, 0x07 }; + +byte gfp_mul(byte x, byte y) + { + if(x == 0 || y == 0) + return 0; + return EXP[(LOG[x] + LOG[y]) % 255]; + } + +byte rtss_hash_id(const std::string& hash_name) + { + if(hash_name == "SHA-160") + return 1; + else if(hash_name == "SHA-256") + return 2; + else + throw Invalid_Argument("RTSS only supports SHA-1 and SHA-256"); + } + +HashFunction* get_rtss_hash_by_id(byte id) + { + if(id == 1) + return new SHA_160; + else if(id == 2) + return new SHA_256; + else + throw Decoding_Error("Bad RTSS hash identifier"); + } + +} + +RTSS_Share::RTSS_Share(const std::string& hex_input) + { + Pipe pipe(new Hex_Decoder); + pipe.process_msg(hex_input); + contents = pipe.read_all(); + } + +byte RTSS_Share::share_id() const + { + if(!initialized()) + throw Invalid_State("RTSS_Share::share_id not initialized"); + + return contents[20]; + } + +std::string RTSS_Share::to_string() const + { + Pipe pipe(new Hex_Encoder); + pipe.process_msg(contents); + return pipe.read_all_as_string(); + } + +std::vector<RTSS_Share> +RTSS_Share::split(byte M, byte N, + const byte S[], u16bit S_len, + const byte identifier[16], + RandomNumberGenerator& rng) + { + if(M == 0 || N == 0 || M > N) + throw Encoding_Error("RTSS_Share::split: M == 0 or N == 0 or M > N"); + + SHA_256 hash; // always use SHA-256 when generating shares + + std::vector<RTSS_Share> shares(N); + + // Create RTSS header in each share + for(byte i = 0; i != N; ++i) + { + shares[i].contents.append(identifier, 16); + shares[i].contents.append(rtss_hash_id(hash.name())); + shares[i].contents.append(M); + shares[i].contents.append(get_byte(0, S_len)); + shares[i].contents.append(get_byte(1, S_len)); + } + + // Choose sequential values for X starting from 1 + for(byte i = 0; i != N; ++i) + shares[i].contents.append(i+1); + + // secret = S || H(S) + SecureVector<byte> secret(S, S_len); + secret.append(hash.process(S, S_len)); + + for(size_t i = 0; i != secret.size(); ++i) + { + std::vector<byte> coefficients(M-1); + rng.randomize(&coefficients[0], coefficients.size()); + + for(byte j = 0; j != N; ++j) + { + const byte X = j + 1; + + byte sum = secret[i]; + byte X_i = X; + + for(size_t k = 0; k != coefficients.size(); ++k) + { + sum ^= gfp_mul(X_i, coefficients[k]); + X_i = gfp_mul(X_i, X); + } + + shares[j].contents.append(sum); + } + } + + return shares; + } + +SecureVector<byte> +RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares) + { + const u32bit RTSS_HEADER_SIZE = 20; + + for(size_t i = 0; i != shares.size(); ++i) + { + if(shares[i].size() != shares[0].size()) + throw Decoding_Error("Different sized RTSS shares detected"); + if(shares[i].share_id() == 0) + throw Decoding_Error("Invalid (id = 0) RTSS share detected"); + if(shares[i].size() < RTSS_HEADER_SIZE) + throw Decoding_Error("Missing or malformed RTSS header"); + + if(!same_mem(shares[0].contents.begin(), + shares[i].contents.begin(), RTSS_HEADER_SIZE)) + throw Decoding_Error("Different RTSS headers detected"); + } + + if(shares.size() < shares[0].contents[17]) + throw Decoding_Error("Insufficient shares to do TSS reconstruction"); + + u16bit secret_len = make_u16bit(shares[0].contents[18], + shares[0].contents[19]); + + byte hash_id = shares[0].contents[16]; + + std::auto_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id)); + + if(shares[0].size() != secret_len + hash->OUTPUT_LENGTH + RTSS_HEADER_SIZE + 1) + throw Decoding_Error("Bad RTSS length field in header"); + + std::vector<byte> V(shares.size()); + SecureVector<byte> secret; + + for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i) + { + for(size_t j = 0; j != V.size(); ++j) + V[j] = shares[j].contents[i]; + + byte r = 0; + for(size_t k = 0; k != shares.size(); ++k) + { + // L_i function: + byte r2 = 1; + for(size_t l = 0; l != shares.size(); ++l) + { + if(k == l) + continue; + + byte share_k = shares[k].share_id(); + byte share_l = shares[l].share_id(); + + if(share_k == share_l) + throw Decoding_Error("Duplicate shares found in RTSS recovery"); + + byte div = EXP[(255 + LOG[share_l] - LOG[share_k ^ share_l]) % 255]; + + r2 = gfp_mul(r2, div); + } + + r ^= gfp_mul(V[k], r2); + } + secret.append(r); + } + + if(secret.size() != secret_len + hash->OUTPUT_LENGTH) + throw Decoding_Error("Bad length in RTSS output"); + + hash->update(secret, secret_len); + SecureVector<byte> hash_check = hash->final(); + + if(!same_mem(hash_check.begin(), secret + secret_len, hash->OUTPUT_LENGTH)) + throw Decoding_Error("RTSS hash check failed"); + + return SecureVector<byte>(secret, secret_len); + } + +} diff --git a/src/tss/tss.h b/src/tss/tss.h new file mode 100644 index 000000000..0b26bfdcb --- /dev/null +++ b/src/tss/tss.h @@ -0,0 +1,55 @@ +/* +* RTSS (threshold secret sharing) +* (C) 2009 Jack Lloyd <[email protected]> +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_RTSS_H__ +#define BOTAN_RTSS_H__ + +#include <botan/secmem.h> +#include <botan/hash.h> +#include <botan/rng.h> +#include <vector> + +namespace Botan { + +class RTSS_Share + { + public: + /** + * @arg M the number of shares needed to reconstruct + * @arg N the number of shares generated + * @arg secret the secret to split + * @arg secret_len the length of the secret + * @arg identifier the 16 byte share identifier + * @arg rng the random number generator to use + */ + static std::vector<RTSS_Share> + split(byte M, byte N, + const byte secret[], u16bit secret_len, + const byte identifier[16], + RandomNumberGenerator& rng); + + /** + * @arg shares the list of shares + */ + static SecureVector<byte> + reconstruct(const std::vector<RTSS_Share>& shares); + + RTSS_Share() {} + RTSS_Share(const std::string&); + + std::string to_string() const; + byte share_id() const; + + u32bit size() const { return contents.size(); } + bool initialized() const { return contents.size(); } + private: + SecureVector<byte> contents; + }; + +} + +#endif diff --git a/src/utils/asm_amd64/info.txt b/src/utils/asm_amd64/info.txt index 19035b545..6fa4d1de5 100644 --- a/src/utils/asm_amd64/info.txt +++ b/src/utils/asm_amd64/info.txt @@ -14,3 +14,7 @@ amd64 gcc icc </cc> + +<requires> +amd64_eng +</requires> diff --git a/src/utils/asm_ia32/info.txt b/src/utils/asm_ia32/info.txt index 4340c35aa..8485d33b9 100644 --- a/src/utils/asm_ia32/info.txt +++ b/src/utils/asm_ia32/info.txt @@ -14,3 +14,7 @@ ia32 gcc icc </cc> + +<requires> +ia32_eng +</requires> diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp new file mode 100644 index 000000000..f79e3a912 --- /dev/null +++ b/src/utils/cpuid.cpp @@ -0,0 +1,101 @@ +/** +* Runtime CPU detection +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cpuid.h> +#include <botan/types.h> +#include <botan/loadstor.h> +#include <botan/mem_ops.h> + +#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64) + +#if defined(BOTAN_BUILD_COMPILER_IS_MSVC) + + #include <intrin.h> + #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0) + +#elif defined(BOTAN_BUILD_COMPILER_IS_ICC) + + #include <ia32intrin.h> + #define CALL_CPUID(type, out) do { __cpuid(out, type) } while(0); + +#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) + + #include <cpuid.h> + #define CALL_CPUID(type, out) \ + do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0); + +#endif + +#endif + +#ifndef CALL_CPUID + // In all other cases, just zeroize the supposed cpuid output + #define CALL_CPUID(type, out) \ + do { out[0] = out[1] = out[2] = out[3] = 0; } while(0); +#endif + +namespace Botan { + +namespace { + +u32bit get_x86_cache_line_size() + { + const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 }; + const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 }; + + u32bit cpuid[4] = { 0 }; + CALL_CPUID(0, cpuid); + + if(same_mem(cpuid + 1, INTEL_CPUID, 3)) + { + CALL_CPUID(1, cpuid); + return 8 * get_byte(2, cpuid[1]); + } + else if(same_mem(cpuid + 1, AMD_CPUID, 3)) + { + CALL_CPUID(0x80000005, cpuid); + return get_byte(3, cpuid[2]); + } + else + return 32; // default cache line guess + } + +} + +/* +* Call the x86 CPUID instruction and return the contents of ecx and +* edx, which contain the feature masks. +*/ +u64bit CPUID::x86_processor_flags() + { + static u64bit proc_flags = 0; + + if(proc_flags) + return proc_flags; + + u32bit cpuid[4] = { 0 }; + CALL_CPUID(1, cpuid); + + // Set the FPU bit on to force caching in proc_flags + proc_flags = ((u64bit)cpuid[2] << 32) | cpuid[3] | 1; + + return proc_flags; + } + +u32bit CPUID::cache_line_size() + { + static u32bit cl_size = 0; + + if(cl_size) + return cl_size; + + cl_size = get_x86_cache_line_size(); + + return cl_size; + } + +} diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h new file mode 100644 index 000000000..0b210768a --- /dev/null +++ b/src/utils/cpuid.h @@ -0,0 +1,74 @@ +/** +* Runtime CPU detection +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CPUID_H__ +#define BOTAN_CPUID_H__ + +#include <botan/types.h> + +namespace Botan { + +class CPUID + { + public: + enum CPUID_bits { + CPUID_RDTSC_BIT = 4, + CPUID_SSE2_BIT = 26, + CPUID_SSSE3_BIT = 41, + CPUID_SSE41_BIT = 51, + CPUID_SSE42_BIT = 52, + CPUID_INTEL_AES_BIT = 57, + }; + + /** + * Return a best guess of the cache line size + */ + static u32bit cache_line_size(); + + /** + * Check if the processor supports RDTSC + */ + static bool has_rdtsc() + { return ((x86_processor_flags() >> CPUID_RDTSC_BIT) & 1); } + + /** + * Check if the processor supports SSE2 + */ + static bool has_sse2() + { return ((x86_processor_flags() >> CPUID_SSE2_BIT) & 1); } + + /** + * Check if the processor supports SSSE3 + */ + static bool has_ssse3() + { return ((x86_processor_flags() >> CPUID_SSSE3_BIT) & 1); } + + /** + * Check if the processor supports SSE4.1 + */ + static bool has_sse41() + { return ((x86_processor_flags() >> CPUID_SSE41_BIT) & 1); } + + /** + * Check if the processor supports SSE4.2 + */ + static bool has_sse42() + { return ((x86_processor_flags() >> CPUID_SSE42_BIT) & 1); } + + /** + * Check if the processor supports Intel AES instructions + */ + static bool has_intel_aes() + { return ((x86_processor_flags() >> CPUID_INTEL_AES_BIT) & 1); } + + private: + static u64bit x86_processor_flags(); + }; + +} + +#endif diff --git a/src/utils/info.txt b/src/utils/info.txt index ab50b88ad..6380fd6c2 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -7,27 +7,3 @@ load_on always <libs> tru64 -> rt </libs> - -<add> -bit_ops.h -bswap.h -charset.cpp -charset.h -exceptn.cpp -exceptn.h -loadstor.h -mem_ops.h -mlock.cpp -parsing.cpp -parsing.h -rotate.h -stl_util.h -types.h -ui.cpp -ui.h -util.cpp -util.h -version.cpp -version.h -xor_buf.h -</add> diff --git a/src/utils/loadstor.h b/src/utils/loadstor.h index 77ed1554e..6f91c2fa5 100644 --- a/src/utils/loadstor.h +++ b/src/utils/loadstor.h @@ -12,6 +12,7 @@ #include <botan/types.h> #include <botan/bswap.h> #include <botan/rotate.h> +#include <botan/prefetch.h> #if BOTAN_TARGET_UNALIGNED_LOADSTOR_OK @@ -165,6 +166,70 @@ inline u64bit load_le<u64bit>(const byte in[], u32bit off) #endif } +template<typename T> +inline void load_le(const byte in[], T& x0, T& x1) + { + x0 = load_le<T>(in, 0); + x1 = load_le<T>(in, 1); + } + +template<typename T> +inline void load_le(const byte in[], + T& x0, T& x1, T& x2, T& x3) + { + x0 = load_le<T>(in, 0); + x1 = load_le<T>(in, 1); + x2 = load_le<T>(in, 2); + x3 = load_le<T>(in, 3); + } + +template<typename T> +inline void load_le(const byte in[], + T& x0, T& x1, T& x2, T& x3, + T& x4, T& x5, T& x6, T& x7) + { + x0 = load_le<T>(in, 0); + x1 = load_le<T>(in, 1); + x2 = load_le<T>(in, 2); + x3 = load_le<T>(in, 3); + x4 = load_le<T>(in, 4); + x5 = load_le<T>(in, 5); + x6 = load_le<T>(in, 6); + x7 = load_le<T>(in, 7); + } + +template<typename T> +inline void load_be(const byte in[], T& x0, T& x1) + { + x0 = load_be<T>(in, 0); + x1 = load_be<T>(in, 1); + } + +template<typename T> +inline void load_be(const byte in[], + T& x0, T& x1, T& x2, T& x3) + { + x0 = load_be<T>(in, 0); + x1 = load_be<T>(in, 1); + x2 = load_be<T>(in, 2); + x3 = load_be<T>(in, 3); + } + +template<typename T> +inline void load_be(const byte in[], + T& x0, T& x1, T& x2, T& x3, + T& x4, T& x5, T& x6, T& x7) + { + x0 = load_be<T>(in, 0); + x1 = load_be<T>(in, 1); + x2 = load_be<T>(in, 2); + x3 = load_be<T>(in, 3); + x4 = load_be<T>(in, 4); + x5 = load_be<T>(in, 5); + x6 = load_be<T>(in, 6); + x7 = load_be<T>(in, 7); + } + /* * Endian-Specific Word Storing Operations */ @@ -245,35 +310,63 @@ inline void store_le(u64bit in, byte out[8]) } template<typename T> -inline void store_le(byte out[], T a, T b) +inline void store_le(byte out[], T x0, T x1) + { + store_le(x0, out + (0 * sizeof(T))); + store_le(x1, out + (1 * sizeof(T))); + } + +template<typename T> +inline void store_be(byte out[], T x0, T x1) + { + store_be(x0, out + (0 * sizeof(T))); + store_be(x1, out + (1 * sizeof(T))); + } + +template<typename T> +inline void store_le(byte out[], T x0, T x1, T x2, T x3) { - store_le(a, out + (0 * sizeof(T))); - store_le(b, out + (1 * sizeof(T))); + store_le(x0, out + (0 * sizeof(T))); + store_le(x1, out + (1 * sizeof(T))); + store_le(x2, out + (2 * sizeof(T))); + store_le(x3, out + (3 * sizeof(T))); } template<typename T> -inline void store_be(byte out[], T a, T b) +inline void store_be(byte out[], T x0, T x1, T x2, T x3) { - store_be(a, out + (0 * sizeof(T))); - store_be(b, out + (1 * sizeof(T))); + store_be(x0, out + (0 * sizeof(T))); + store_be(x1, out + (1 * sizeof(T))); + store_be(x2, out + (2 * sizeof(T))); + store_be(x3, out + (3 * sizeof(T))); } template<typename T> -inline void store_le(byte out[], T a, T b, T c, T d) +inline void store_le(byte out[], T x0, T x1, T x2, T x3, + T x4, T x5, T x6, T x7) { - store_le(a, out + (0 * sizeof(T))); - store_le(b, out + (1 * sizeof(T))); - store_le(c, out + (2 * sizeof(T))); - store_le(d, out + (3 * sizeof(T))); + store_le(x0, out + (0 * sizeof(T))); + store_le(x1, out + (1 * sizeof(T))); + store_le(x2, out + (2 * sizeof(T))); + store_le(x3, out + (3 * sizeof(T))); + store_le(x4, out + (4 * sizeof(T))); + store_le(x5, out + (5 * sizeof(T))); + store_le(x6, out + (6 * sizeof(T))); + store_le(x7, out + (7 * sizeof(T))); } template<typename T> -inline void store_be(byte out[], T a, T b, T c, T d) +inline void store_be(byte out[], T x0, T x1, T x2, T x3, + T x4, T x5, T x6, T x7) { - store_be(a, out + (0 * sizeof(T))); - store_be(b, out + (1 * sizeof(T))); - store_be(c, out + (2 * sizeof(T))); - store_be(d, out + (3 * sizeof(T))); + store_be(x0, out + (0 * sizeof(T))); + store_be(x1, out + (1 * sizeof(T))); + store_be(x2, out + (2 * sizeof(T))); + store_be(x3, out + (3 * sizeof(T))); + store_be(x4, out + (4 * sizeof(T))); + store_be(x5, out + (5 * sizeof(T))); + store_be(x6, out + (6 * sizeof(T))); + store_be(x7, out + (7 * sizeof(T))); } } diff --git a/src/utils/mlock.cpp b/src/utils/mlock.cpp index 9bb062da5..6453d8a30 100644 --- a/src/utils/mlock.cpp +++ b/src/utils/mlock.cpp @@ -5,7 +5,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/util.h> +#include <botan/mlock.h> #if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) #include <sys/types.h> diff --git a/src/utils/mlock.h b/src/utils/mlock.h new file mode 100644 index 000000000..0811e8190 --- /dev/null +++ b/src/utils/mlock.h @@ -0,0 +1,32 @@ +/* +* Memory Locking Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_MLOCK_H__ +#define BOTAN_MLOCK_H__ + +#include <botan/types.h> + +namespace Botan { + +/** +* Lock memory into RAM if possible +* @param addr the start of the memory block +* @param length the length of the memory block in bytes +* @returns true if successful, false otherwise +*/ +BOTAN_DLL bool lock_mem(void* addr, u32bit length); + +/** +* Unlock memory locked with lock_mem() +* @param addr the start of the memory block +* @param length the length of the memory block in bytes +*/ +BOTAN_DLL void unlock_mem(void* addr, u32bit length); + +} + +#endif diff --git a/src/utils/parsing.cpp b/src/utils/parsing.cpp index bdb9e79dc..58a8e0b38 100644 --- a/src/utils/parsing.cpp +++ b/src/utils/parsing.cpp @@ -23,6 +23,9 @@ u32bit to_u32bit(const std::string& number) { const u32bit OVERFLOW_MARK = 0xFFFFFFFF / 10; + if(*j == ' ') + continue; + byte digit = Charset::char2digit(*j); if((n > OVERFLOW_MARK) || (n == OVERFLOW_MARK && digit > 5)) diff --git a/src/utils/prefetch.h b/src/utils/prefetch.h new file mode 100644 index 000000000..7afdbda0a --- /dev/null +++ b/src/utils/prefetch.h @@ -0,0 +1,43 @@ +/* +* Prefetching Operations +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PREFETCH_H__ +#define BOTAN_PREFETCH_H__ + +#include <botan/cpuid.h> + +namespace Botan { + +namespace PREFETCH { + +template<typename T> +inline void readonly(const T* addr, u32bit length) + { +#if defined(__GNUG__) + const u32bit Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); + + for(u32bit i = 0; i <= length; i += Ts_per_cache_line) + __builtin_prefetch(addr + i, 0); +#endif + } + +template<typename T> +inline void readwrite(const T* addr, u32bit length) + { +#if defined(__GNUG__) + const u32bit Ts_per_cache_line = CPUID::cache_line_size() / sizeof(T); + + for(u32bit i = 0; i <= length; i += Ts_per_cache_line) + __builtin_prefetch(addr + i, 0); +#endif + } + +} + +} + +#endif diff --git a/src/utils/rounding.h b/src/utils/rounding.h new file mode 100644 index 000000000..11ab90b8d --- /dev/null +++ b/src/utils/rounding.h @@ -0,0 +1,35 @@ +/* +* Integer Rounding Functions +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ROUNDING_H__ +#define BOTAN_ROUNDING_H__ + +#include <botan/types.h> + +namespace Botan { + +/* +* Round up n to multiple of align_to +*/ +inline u32bit round_up(u32bit n, u32bit align_to) + { + if(n % align_to || n == 0) + n += align_to - (n % align_to); + return n; + } + +/* +* Round down n to multiple of align_to +*/ +inline u32bit round_down(u32bit n, u32bit align_to) + { + return (n - (n % align_to)); + } + +} + +#endif diff --git a/src/utils/util.h b/src/utils/util.h deleted file mode 100644 index ac7867390..000000000 --- a/src/utils/util.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Utility Functions -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_UTIL_H__ -#define BOTAN_UTIL_H__ - -#include <botan/types.h> - -namespace Botan { - -/* -* Time Access Functions -*/ -BOTAN_DLL u64bit system_time(); - -/* -* Memory Locking Functions -*/ -BOTAN_DLL bool lock_mem(void*, u32bit); -BOTAN_DLL void unlock_mem(void*, u32bit); - -/* -* Misc Utility Functions -*/ -BOTAN_DLL u32bit round_up(u32bit, u32bit); -BOTAN_DLL u32bit round_down(u32bit, u32bit); - -/* -* Work Factor Estimates -*/ -BOTAN_DLL u32bit dl_work_factor(u32bit); - -} - -#endif diff --git a/wrappers/perl-xs/Botan.pm b/src/wrap/perl-xs/Botan.pm index ac4ad91fb..ac4ad91fb 100644 --- a/wrappers/perl-xs/Botan.pm +++ b/src/wrap/perl-xs/Botan.pm diff --git a/wrappers/perl-xs/Botan.xs b/src/wrap/perl-xs/Botan.xs index ded129d2e..ded129d2e 100644 --- a/wrappers/perl-xs/Botan.xs +++ b/src/wrap/perl-xs/Botan.xs diff --git a/wrappers/perl-xs/Changes b/src/wrap/perl-xs/Changes index 5f32b0c63..5f32b0c63 100644 --- a/wrappers/perl-xs/Changes +++ b/src/wrap/perl-xs/Changes diff --git a/wrappers/perl-xs/MANIFEST b/src/wrap/perl-xs/MANIFEST index b9d8454d6..b9d8454d6 100644 --- a/wrappers/perl-xs/MANIFEST +++ b/src/wrap/perl-xs/MANIFEST diff --git a/wrappers/perl-xs/Makefile.PL b/src/wrap/perl-xs/Makefile.PL index d35c99168..46317e72b 100644 --- a/wrappers/perl-xs/Makefile.PL +++ b/src/wrap/perl-xs/Makefile.PL @@ -9,7 +9,7 @@ if ( $^O eq 'MSWin32' ) else { $cc = 'g++'; - $cflags = '-fexceptions ' . qx( botan-config --cflags ); + $cflags = '-Wno-write-strings -fexceptions ' . qx( botan-config --cflags ); $libs = qx( botan-config --libs ); } diff --git a/wrappers/perl-xs/data/ca.cert.der b/src/wrap/perl-xs/data/ca.cert.der Binary files differindex d6ed8aeaf..d6ed8aeaf 100644 --- a/wrappers/perl-xs/data/ca.cert.der +++ b/src/wrap/perl-xs/data/ca.cert.der diff --git a/wrappers/perl-xs/data/ca.cert.pem b/src/wrap/perl-xs/data/ca.cert.pem index 012913b26..012913b26 100644 --- a/wrappers/perl-xs/data/ca.cert.pem +++ b/src/wrap/perl-xs/data/ca.cert.pem diff --git a/wrappers/perl-xs/t/base64.t b/src/wrap/perl-xs/t/base64.t index f0973e13e..f0973e13e 100644 --- a/wrappers/perl-xs/t/base64.t +++ b/src/wrap/perl-xs/t/base64.t diff --git a/wrappers/perl-xs/t/filt.t b/src/wrap/perl-xs/t/filt.t index 2a7b4c8ba..2a7b4c8ba 100644 --- a/wrappers/perl-xs/t/filt.t +++ b/src/wrap/perl-xs/t/filt.t diff --git a/wrappers/perl-xs/t/hex.t b/src/wrap/perl-xs/t/hex.t index 6f447b25c..6f447b25c 100644 --- a/wrappers/perl-xs/t/hex.t +++ b/src/wrap/perl-xs/t/hex.t diff --git a/wrappers/perl-xs/t/oid.t b/src/wrap/perl-xs/t/oid.t index 66204541f..66204541f 100644 --- a/wrappers/perl-xs/t/oid.t +++ b/src/wrap/perl-xs/t/oid.t diff --git a/wrappers/perl-xs/t/pipe.t b/src/wrap/perl-xs/t/pipe.t index f850d8519..f850d8519 100644 --- a/wrappers/perl-xs/t/pipe.t +++ b/src/wrap/perl-xs/t/pipe.t diff --git a/wrappers/perl-xs/t/testutl.pl b/src/wrap/perl-xs/t/testutl.pl index add6f6a45..add6f6a45 100644 --- a/wrappers/perl-xs/t/testutl.pl +++ b/src/wrap/perl-xs/t/testutl.pl diff --git a/wrappers/perl-xs/t/x509cert.t b/src/wrap/perl-xs/t/x509cert.t index 2a943aeac..2a943aeac 100644 --- a/wrappers/perl-xs/t/x509cert.t +++ b/src/wrap/perl-xs/t/x509cert.t diff --git a/wrappers/perl-xs/typemap b/src/wrap/perl-xs/typemap index d7403d40d..d7403d40d 100644 --- a/wrappers/perl-xs/typemap +++ b/src/wrap/perl-xs/typemap diff --git a/src/wrap/python/__init__.py b/src/wrap/python/__init__.py new file mode 100644 index 000000000..2df9a456f --- /dev/null +++ b/src/wrap/python/__init__.py @@ -0,0 +1,4 @@ +from _botan import * + +# Initialize the library when the module is imported +init = LibraryInitializer() diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp new file mode 100644 index 000000000..fe26e16ee --- /dev/null +++ b/src/wrap/python/core.cpp @@ -0,0 +1,216 @@ +/* +* Boost.Python module definition +* (C) 1999-2007 Jack Lloyd +*/ + +#include <botan/init.h> +#include <botan/pipe.h> +#include <botan/lookup.h> +#include <botan/cryptobox.h> +#include <botan/pbkdf2.h> +#include <botan/hmac.h> +using namespace Botan; + +#include "python_botan.h" + +class Py_Cipher + { + public: + Py_Cipher(std::string algo_name, std::string direction, + std::string key); + + std::string cipher_noiv(const std::string& text); + + std::string cipher(const std::string& text, + const std::string& iv); + + std::string name() const { return algo_name; } + private: + std::string algo_name; + Keyed_Filter* filter; + Pipe pipe; + }; + +std::string Py_Cipher::cipher(const std::string& input, + const std::string& iv_str) + { + if(iv_str.size()) + { + const byte* iv_bytes = reinterpret_cast<const byte*>(iv_str.data()); + u32bit iv_len = iv_str.size(); + filter->set_iv(InitializationVector(iv_bytes, iv_len)); + } + + pipe.process_msg(input); + return pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +// For IV-less algorithms +std::string Py_Cipher::cipher_noiv(const std::string& input) + { + pipe.process_msg(input); + return pipe.read_all_as_string(Pipe::LAST_MESSAGE); + } + +Py_Cipher::Py_Cipher(std::string algo_name, + std::string direction, + std::string key_str) + { + const byte* key_bytes = reinterpret_cast<const byte*>(key_str.data()); + u32bit key_len = key_str.size(); + + Cipher_Dir dir; + + if(direction == "encrypt") + dir = ENCRYPTION; + else if(direction == "decrypt") + dir = DECRYPTION; + else + throw std::invalid_argument("Bad cipher direction " + direction); + + filter = get_cipher(algo_name, dir); + filter->set_key(SymmetricKey(key_bytes, key_len)); + pipe.append(filter); + } + +class Py_HashFunction + { + public: + Py_HashFunction(const std::string& algo_name) + { + hash = get_hash(algo_name); + } + + ~Py_HashFunction() { delete hash; } + + void update(const std::string& input) + { + hash->update(input); + } + + std::string final() + { + std::string out(output_length(), 0); + hash->final(reinterpret_cast<byte*>(&out[0])); + return out; + } + + std::string name() const + { + return hash->name(); + } + + u32bit output_length() const + { + return hash->OUTPUT_LENGTH; + } + + private: + HashFunction* hash; + }; + +class Py_MAC + { + public: + + Py_MAC(const std::string& name, const std::string& key_str) + { + mac = get_mac(name); + + mac->set_key(reinterpret_cast<const byte*>(key_str.data()), + key_str.size()); + } + + ~Py_MAC() { delete mac; } + + u32bit output_length() const { return mac->OUTPUT_LENGTH; } + + std::string name() const { return mac->name(); } + + void update(const std::string& in) { mac->update(in); } + + std::string final() + { + std::string out(output_length(), 0); + mac->final(reinterpret_cast<byte*>(&out[0])); + return out; + } + private: + MessageAuthenticationCode* mac; + }; + +std::string cryptobox_encrypt(const std::string& in, + const std::string& passphrase, + Python_RandomNumberGenerator& rng) + { + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return CryptoBox::encrypt(in_bytes, in.size(), + passphrase, rng.get_underlying_rng()); + } + +std::string cryptobox_decrypt(const std::string& in, + const std::string& passphrase) + { + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return CryptoBox::decrypt(in_bytes, in.size(), + passphrase); + } + +std::string python_pbkdf2(const std::string& passphrase, + const std::string& salt, + u32bit iterations, + u32bit output_size, + const std::string& hash_fn) + { + PKCS5_PBKDF2 pbkdf2(new HMAC(get_hash(hash_fn))); + + pbkdf2.set_iterations(iterations); + pbkdf2.change_salt(reinterpret_cast<const byte*>(salt.data()), salt.size()); + + return make_string(pbkdf2.derive_key(output_size, passphrase).bits_of()); + } + +BOOST_PYTHON_MODULE(_botan) + { + python::class_<LibraryInitializer>("LibraryInitializer") + .def(python::init< python::optional<std::string> >()); + + python::class_<Python_RandomNumberGenerator>("RandomNumberGenerator") + .def(python::init<>()) + .def("__str__", &Python_RandomNumberGenerator::name) + .def("name", &Python_RandomNumberGenerator::name) + .def("reseed", &Python_RandomNumberGenerator::reseed) + .def("add_entropy", &Python_RandomNumberGenerator::add_entropy) + .def("gen_random_byte", &Python_RandomNumberGenerator::gen_random_byte) + .def("gen_random", &Python_RandomNumberGenerator::gen_random); + + python::class_<Py_Cipher, boost::noncopyable> + ("Cipher", python::init<std::string, std::string, std::string>()) + .def("name", &Py_Cipher::name) + .def("cipher", &Py_Cipher::cipher) + .def("cipher", &Py_Cipher::cipher_noiv); + + python::class_<Py_HashFunction, boost::noncopyable> + ("HashFunction", python::init<std::string>()) + .def("update", &Py_HashFunction::update) + .def("final", &Py_HashFunction::final) + .def("name", &Py_HashFunction::name) + .def("output_length", &Py_HashFunction::output_length); + + python::class_<Py_MAC, boost::noncopyable> + ("MAC", python::init<std::string, std::string>()) + .def("update", &Py_MAC::update) + .def("final", &Py_MAC::final) + .def("name", &Py_MAC::name) + .def("output_length", &Py_MAC::output_length); + + python::def("cryptobox_encrypt", cryptobox_encrypt); + python::def("cryptobox_decrypt", cryptobox_decrypt); + python::def("pbkdf2", python_pbkdf2); + + export_filters(); + export_rsa(); + export_x509(); + } diff --git a/wrappers/boost-python/src/filter.cpp b/src/wrap/python/filter.cpp index 830e090de..a678af9e5 100644 --- a/wrappers/boost-python/src/filter.cpp +++ b/src/wrap/python/filter.cpp @@ -159,8 +159,10 @@ void export_filters() class_<Pipe, boost::noncopyable>("PipeObj") .def(init<>()) + /* .def_readonly("LAST_MESSAGE", &Pipe::LAST_MESSAGE) .def_readonly("DEFAULT_MESSAGE", &Pipe::DEFAULT_MESSAGE) + */ .add_property("default_msg", &Pipe::default_msg, &Pipe::set_default_msg) .add_property("msg_count", &Pipe::message_count) .def("append", append_filter) diff --git a/wrappers/boost-python/src/python_botan.h b/src/wrap/python/python_botan.h index d0fd10207..646c2e2c1 100644 --- a/wrappers/boost-python/src/python_botan.h +++ b/src/wrap/python/python_botan.h @@ -2,19 +2,16 @@ #ifndef BOTAN_BOOST_PYTHON_COMMON_H__ #define BOTAN_BOOST_PYTHON_COMMON_H__ -#include <botan/base.h> +#include <botan/exceptn.h> +#include <botan/parsing.h> +#include <botan/secmem.h> using namespace Botan; #include <boost/python.hpp> namespace python = boost::python; - -extern void export_block_ciphers(); -extern void export_stream_ciphers(); -extern void export_hash_functions(); -extern void export_macs(); extern void export_filters(); -extern void export_pk(); +extern void export_rsa(); extern void export_x509(); class Bad_Size : public Exception @@ -51,4 +48,32 @@ inline python::object get_owner(T* me) python::borrowed(python::detail::wrapper_base_::get_owner(*me)))); } +class Python_RandomNumberGenerator + { + public: + Python_RandomNumberGenerator() + { rng = RandomNumberGenerator::make_rng(); } + ~Python_RandomNumberGenerator() { delete rng; } + + std::string name() const { return rng->name(); } + + void reseed() { rng->reseed(192); } + + int gen_random_byte() { return rng->next_byte(); } + + std::string gen_random(int n) + { + std::string s(n, 0); + rng->randomize(reinterpret_cast<byte*>(&s[0]), n); + return s; + } + + void add_entropy(const std::string& in) + { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); } + + RandomNumberGenerator& get_underlying_rng() { return *rng; } + private: + RandomNumberGenerator* rng; + }; + #endif diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp new file mode 100644 index 000000000..900c3f93d --- /dev/null +++ b/src/wrap/python/rsa.cpp @@ -0,0 +1,187 @@ +/* +* Boost.Python module definition +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/rsa.h> +#include <botan/look_pk.h> +#include <botan/pubkey.h> +#include <botan/x509_key.h> +using namespace Botan; + +#include "python_botan.h" +#include <sstream> + +std::string bigint2str(const BigInt& n) + { + std::ostringstream out; + out << n; + return out.str(); + } + +class Py_RSA_PrivateKey + { + public: + Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string pass); + + Py_RSA_PrivateKey(u32bit bits, Python_RandomNumberGenerator& rng); + ~Py_RSA_PrivateKey() { delete rsa_key; } + + std::string to_string() const + { + return PKCS8::PEM_encode(*rsa_key); + } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string decrypt(const std::string& in, + const std::string& padding); + + std::string sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + private: + RSA_PrivateKey* rsa_key; + }; + +std::string Py_RSA_PrivateKey::decrypt(const std::string& in, + const std::string& padding) + { + std::auto_ptr<PK_Decryptor> enc(get_pk_decryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return make_string(enc->decrypt(in_bytes, in.size())); + } + +std::string Py_RSA_PrivateKey::sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Signer> sign(get_pk_signer(*rsa_key, padding)); + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + sign->update(in_bytes, in.size()); + return make_string(sign->signature(rng.get_underlying_rng())); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(u32bit bits, + Python_RandomNumberGenerator& rng) + { + rsa_key = new RSA_PrivateKey(rng.get_underlying_rng(), bits); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string passphrase) + { + DataSource_Memory in(pem_str); + + Private_Key* pkcs8_key = + PKCS8::load_key(in, + rng.get_underlying_rng(), + passphrase); + + rsa_key = dynamic_cast<RSA_PrivateKey*>(pkcs8_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +class Py_RSA_PublicKey + { + public: + Py_RSA_PublicKey(std::string pem_str); + Py_RSA_PublicKey(const Py_RSA_PrivateKey&); + ~Py_RSA_PublicKey() { delete rsa_key; } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string to_string() const + { + return X509::PEM_encode(*rsa_key); + } + + std::string encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + + bool verify(const std::string& in, + const std::string& padding, + const std::string& signature); + private: + RSA_PublicKey* rsa_key; + }; + +Py_RSA_PublicKey::Py_RSA_PublicKey(const Py_RSA_PrivateKey& priv) + { + rsa_key = new RSA_PublicKey(priv.get_bigint_N(), priv.get_bigint_E()); + } + +Py_RSA_PublicKey::Py_RSA_PublicKey(std::string pem_str) + { + DataSource_Memory in(pem_str); + Public_Key* x509_key = X509::load_key(in); + + rsa_key = dynamic_cast<RSA_PublicKey*>(x509_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +std::string Py_RSA_PublicKey::encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return make_string(enc->encrypt(in_bytes, in.size(), + rng.get_underlying_rng())); + } + +bool Py_RSA_PublicKey::verify(const std::string& in, + const std::string& signature, + const std::string& padding) + { + std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + const byte* sig_bytes = reinterpret_cast<const byte*>(signature.data()); + + ver->update(in_bytes, in.size()); + return ver->check_signature(sig_bytes, signature.size()); + } + +void export_rsa() + { + python::class_<Py_RSA_PublicKey> + ("RSA_PublicKey", python::init<std::string>()) + .def(python::init<const Py_RSA_PrivateKey&>()) + .def("to_string", &Py_RSA_PublicKey::to_string) + .def("encrypt", &Py_RSA_PublicKey::encrypt) + .def("verify", &Py_RSA_PublicKey::verify) + .def("get_N", &Py_RSA_PublicKey::get_N) + .def("get_E", &Py_RSA_PublicKey::get_E); + + python::class_<Py_RSA_PrivateKey> + ("RSA_PrivateKey", python::init<std::string, Python_RandomNumberGenerator&, std::string>()) + .def(python::init<u32bit, Python_RandomNumberGenerator&>()) + .def("to_string", &Py_RSA_PrivateKey::to_string) + .def("decrypt", &Py_RSA_PrivateKey::decrypt) + .def("sign", &Py_RSA_PrivateKey::sign) + .def("get_N", &Py_RSA_PrivateKey::get_N) + .def("get_E", &Py_RSA_PrivateKey::get_E); + } diff --git a/wrappers/boost-python/src/x509.cpp b/src/wrap/python/x509.cpp index 90c2bba1c..90c2bba1c 100644 --- a/wrappers/boost-python/src/x509.cpp +++ b/src/wrap/python/x509.cpp diff --git a/wrappers/boost-python/Makefile b/wrappers/boost-python/Makefile deleted file mode 100644 index e3a1acf37..000000000 --- a/wrappers/boost-python/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -CXX = g++ -LANG_FLAGS = -fPIC -Wall -Wno-unused -ftemplate-depth-255 -OPT_FLAGS = -g -Os - -PYTHON_ROOT = /usr/lib/python2.5/config -PYTHON_INC = -I/usr/include/python2.5 -PYTHON_DEF = -DBOOST_PYTHON_DYNAMIC_LIB -DBOOST_PYTHON_SOURCE - -WRAPPER_CFLAGS = $(shell botan-config --cflags) -SHARED_CFLAGS = $(LANG_FLAGS) $(OPT_FLAGS) $(PYTHON_INC) - -BOOST_CFLAGS = $(PYTHON_DEF) $(SHARED_CFLAGS) - -WRAP_SRC = $(wildcard src/*.cpp) -WRAP_OBJS = $(patsubst src/%.cpp,build/%.o,$(WRAP_SRC)) - -all: botan/_botan.so - -build/%.o: src/%.cpp - $(CXX) -Isrc/ $(SHARED_CFLAGS) $(WRAPPER_CFLAGS) -c $< -o $@ - -botan/_botan.so: $(WRAP_OBJS) - $(CXX) -shared -o $@ $(shell botan-config --libs) -L$(PYTHON_ROOT) $(WRAP_OBJS) -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@ - -clean: - rm -f $(WRAP_OBJS) botan/_botan.so botan/*.pyc diff --git a/wrappers/boost-python/botan/__init__.py b/wrappers/boost-python/botan/__init__.py deleted file mode 100644 index 9e136ed39..000000000 --- a/wrappers/boost-python/botan/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -from _botan import * - -# Initialize the library when the module is imported -init = LibraryInitializer() - -class SymmetricKey(OctetString): - pass - -class InitializationVector(OctetString): - pass - -def Filter(name, key = None, iv = None, dir = None): - if key != None and iv != None and dir != None: - return make_filter(name, key, iv, dir) - elif key != None and dir != None: - return make_filter(name, key, dir) - elif key != None: - return make_filter(name, key) - else: - return make_filter(name) - -def Pipe(*filters): - pipe = PipeObj() - for filter in filters: - if filter: - pipe.append(filter) - return pipe diff --git a/wrappers/boost-python/src/block.cpp b/wrappers/boost-python/src/block.cpp deleted file mode 100644 index 185b88811..000000000 --- a/wrappers/boost-python/src/block.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/botan.h> -using namespace Botan; - -#include "python_botan.h" - -class Py_BlockCipher : public BlockCipher - { - public: - virtual std::string enc_str(const std::string&) const = 0; - virtual std::string dec_str(const std::string&) const = 0; - virtual void set_key_obj(const OctetString&) = 0; - - void clear() throw() {} - - void enc(const byte in[], byte out[]) const - { - string2binary( - enc_str(make_string(in, BLOCK_SIZE)), - out, BLOCK_SIZE); - } - - void dec(const byte in[], byte out[]) const - { - string2binary( - dec_str(make_string(in, BLOCK_SIZE)), - out, BLOCK_SIZE); - } - - void key(const byte key[], u32bit len) - { - set_key_obj(OctetString(key, len)); - } - - Py_BlockCipher(u32bit bs, u32bit kmin, u32bit kmax, u32bit kmod) : - BlockCipher(bs, kmin, kmax, kmod) - { - } - }; - -std::string encrypt_string(BlockCipher* cipher, const std::string& in) - { - if(in.size() != cipher->BLOCK_SIZE) - throw Bad_Size(in.size(), cipher->BLOCK_SIZE); - - SecureVector<byte> out(cipher->BLOCK_SIZE); - cipher->encrypt((const byte*)in.data(), out); - return make_string(out); - } - -std::string decrypt_string(BlockCipher* cipher, const std::string& in) - { - if(in.size() != cipher->BLOCK_SIZE) - throw Bad_Size(in.size(), cipher->BLOCK_SIZE); - - SecureVector<byte> out(cipher->BLOCK_SIZE); - cipher->decrypt((const byte*)in.data(), out); - return make_string(out); - } - -class Wrapped_Block_Cipher : public BlockCipher - { - public: - void clear() throw() { cipher->clear(); } - - void enc(const byte in[], byte out[]) const { cipher->encrypt(in, out); } - void dec(const byte in[], byte out[]) const { cipher->decrypt(in, out); } - void key(const byte key[], u32bit len) { cipher->set_key(key, len); } - std::string name() const { return cipher->name(); } - BlockCipher* clone() const { return cipher->clone(); } - - Wrapped_Block_Cipher(python::object py_obj, BlockCipher* c) : - BlockCipher(c->BLOCK_SIZE, c->MINIMUM_KEYLENGTH, - c->MAXIMUM_KEYLENGTH, c->KEYLENGTH_MULTIPLE), - obj(py_obj), cipher(c) {} - private: - python::object obj; - BlockCipher* cipher; - }; - -class Py_BlockCipher_Wrapper : public Py_BlockCipher, - public python::wrapper<Py_BlockCipher> - { - public: - BlockCipher* clone() const - { - python::object self = get_owner(this); - python::object py_clone = self.attr("__class__")(); - BlockCipher* bc = python::extract<BlockCipher*>(py_clone); - return new Wrapped_Block_Cipher(py_clone, bc); - } - - void clear() throw() - { - this->get_override("clear")(); - } - - std::string name() const - { - return this->get_override("name")(); - } - - std::string enc_str(const std::string& in) const - { - return this->get_override("encrypt")(in); - } - - std::string dec_str(const std::string& in) const - { - return this->get_override("decrypt")(in); - } - - void set_key_obj(const OctetString& key) - { - this->get_override("set_key")(key); - } - - Py_BlockCipher_Wrapper(u32bit bs, u32bit kmin, - u32bit kmax, u32bit kmod) : - Py_BlockCipher(bs, kmin, kmax, kmod) {} - }; - -void export_block_ciphers() - { - void (BlockCipher::*set_key_ptr)(const OctetString&) = - &BlockCipher::set_key; - - python::class_<BlockCipher, boost::noncopyable> - ("BlockCipher", python::no_init) - .def("__init__", python::make_constructor(get_block_cipher)) - .def_readonly("block_size", &BlockCipher::BLOCK_SIZE) - .def_readonly("keylength_min", &BlockCipher::MINIMUM_KEYLENGTH) - .def_readonly("keylength_max", &BlockCipher::MAXIMUM_KEYLENGTH) - .def_readonly("keylength_mod", &BlockCipher::KEYLENGTH_MULTIPLE) - .def("valid_keylength", &BlockCipher::valid_keylength) - .def("name", &BlockCipher::name) - .def("set_key", set_key_ptr) - .def("encrypt", encrypt_string) - .def("decrypt", decrypt_string); - - python::class_<Py_BlockCipher_Wrapper, python::bases<BlockCipher>, - boost::noncopyable> - ("BlockCipherImpl", python::init<u32bit, u32bit, u32bit, u32bit>()) - .def("name", python::pure_virtual(&Py_BlockCipher::name)) - .def("encrypt", python::pure_virtual(&Py_BlockCipher::enc_str)) - .def("decrypt", python::pure_virtual(&Py_BlockCipher::dec_str)) - .def("set_key", python::pure_virtual(&Py_BlockCipher::set_key_obj)); - } diff --git a/wrappers/boost-python/src/core.cpp b/wrappers/boost-python/src/core.cpp deleted file mode 100644 index 7ef2a9970..000000000 --- a/wrappers/boost-python/src/core.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/botan.h> -using namespace Botan; - -#include <boost/python.hpp> -namespace python = boost::python; - -#include "python_botan.h" - -class Python_RandomNumberGenerator - { - public: - Python_RandomNumberGenerator() - { rng = RandomNumberGenerator::make_rng(); } - ~Python_RandomNumberGenerator() { delete rng; } - - std::string name() const { return rng->name(); } - - void reseed() { rng->reseed(); } - - int gen_random_byte() { return rng->next_byte(); } - - std::string gen_random(int n) - { - std::string s(n, 0); - rng->randomize(reinterpret_cast<byte*>(&s[0]), n); - return s; - } - - void add_entropy(const std::string& in) - { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); } - - private: - RandomNumberGenerator* rng; - }; - -BOOST_PYTHON_MODULE(_botan) - { - python::class_<LibraryInitializer>("LibraryInitializer") - .def(python::init< python::optional<std::string> >()); - - python::class_<Python_RandomNumberGenerator>("RandomNumberGenerator") - .def(python::init<>()) - .def("__str__", &Python_RandomNumberGenerator::name) - .def("name", &Python_RandomNumberGenerator::name) - .def("reseed", &Python_RandomNumberGenerator::reseed) - .def("add_entropy", &Python_RandomNumberGenerator::add_entropy) - .def("gen_random_byte", &Python_RandomNumberGenerator::gen_random_byte) - .def("gen_random", &Python_RandomNumberGenerator::gen_random); - - python::class_<OctetString>("OctetString") - .def(python::init< python::optional<std::string> >()) - //.def(python::init< u32bit >()) - .def("__str__", &OctetString::as_string) - .def("__len__", &OctetString::length); - - python::enum_<Cipher_Dir>("cipher_dir") - .value("encryption", ENCRYPTION) - .value("decryption", DECRYPTION); - - export_block_ciphers(); - export_stream_ciphers(); - export_hash_functions(); - export_macs(); - - export_filters(); - export_pk(); - export_x509(); - } diff --git a/wrappers/boost-python/src/hash.cpp b/wrappers/boost-python/src/hash.cpp deleted file mode 100644 index 6ef198087..000000000 --- a/wrappers/boost-python/src/hash.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/botan.h> -using namespace Botan; - -#include "python_botan.h" - -class Py_HashFunction : public HashFunction - { - public: - virtual void hash_str(const std::string&) = 0; - virtual std::string final_str() = 0; - - void clear() throw() {} - - void add_data(const byte input[], u32bit length) - { - hash_str(make_string(input, length)); - } - - void final_result(byte output[]) - { - string2binary(final_str(), output, OUTPUT_LENGTH); - } - - Py_HashFunction(u32bit digest_size, u32bit block_size) : - HashFunction(digest_size, block_size) {} - }; - -class Wrapped_HashFunction : public HashFunction - { - public: - void add_data(const byte in[], u32bit len) { hash->update(in, len); } - void final_result(byte out[]) { hash->final(out); } - - void clear() throw() {} - - std::string name() const { return hash->name(); } - HashFunction* clone() const { return hash->clone(); } - - Wrapped_HashFunction(python::object py_obj, HashFunction* h) : - HashFunction(h->OUTPUT_LENGTH, h->HASH_BLOCK_SIZE), - obj(py_obj), hash(h) {} - private: - python::object obj; - HashFunction* hash; - }; - -class Py_HashFunction_Wrapper : public Py_HashFunction, - public python::wrapper<Py_HashFunction> - { - public: - HashFunction* clone() const - { - python::object self = get_owner(this); - python::object py_clone = self.attr("__class__")(); - HashFunction* hf = python::extract<HashFunction*>(py_clone); - return new Wrapped_HashFunction(py_clone, hf); - } - - std::string name() const - { - return this->get_override("name")(); - } - - void hash_str(const std::string& in) - { - this->get_override("update")(in); - } - - std::string final_str() - { - return this->get_override("final")(); - } - - Py_HashFunction_Wrapper(u32bit digest_size, u32bit block_size) : - Py_HashFunction(digest_size, block_size) {} - }; - -std::string final_str(HashFunction* hash) - { - SecureVector<byte> digest = hash->final(); - return std::string((const char*)digest.begin(), digest.size()); - } - -void export_hash_functions() - { - void (HashFunction::*update_str)(const std::string&) = - &HashFunction::update; - - python::class_<HashFunction, boost::noncopyable> - ("HashFunction", python::no_init) - .def("__init__", python::make_constructor(get_hash)) - .def_readonly("digest_size", &HashFunction::OUTPUT_LENGTH) - .def("name", &HashFunction::name) - .def("update", update_str) - .def("final", final_str); - - python::class_<Py_HashFunction_Wrapper, python::bases<HashFunction>, - boost::noncopyable> - ("HashFunctionImpl", python::init<u32bit, u32bit>()) - .def("name", python::pure_virtual(&Py_HashFunction::name)) - .def("update", python::pure_virtual(&Py_HashFunction::hash_str)) - .def("final", python::pure_virtual(&Py_HashFunction::final_str)); - } diff --git a/wrappers/boost-python/src/macs.cpp b/wrappers/boost-python/src/macs.cpp deleted file mode 100644 index 54a55afe2..000000000 --- a/wrappers/boost-python/src/macs.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/botan.h> -using namespace Botan; - -#include <boost/python.hpp> -namespace python = boost::python; - -class Py_MAC - { - public: - u32bit output_length() const { return mac->OUTPUT_LENGTH; } - u32bit keylength_min() const { return mac->MINIMUM_KEYLENGTH; } - u32bit keylength_max() const { return mac->MAXIMUM_KEYLENGTH; } - u32bit keylength_mod() const { return mac->KEYLENGTH_MULTIPLE; } - std::string name() const { return mac->name(); } - void clear() throw() { mac->clear(); } - - void set_key(const OctetString& key) { mac->set_key(key); } - - bool valid_keylength(u32bit kl) const - { - return mac->valid_keylength(kl); - } - - void update(const std::string& in) { mac->update(in); } - - std::string final() - { - SecureVector<byte> result = mac->final(); - return std::string((const char*)result.begin(), result.size()); - } - - Py_MAC(const std::string& name) - { - mac = get_mac(name); - } - ~Py_MAC() { delete mac; } - private: - MessageAuthenticationCode* mac; - }; - -void export_macs() - { - python::class_<Py_MAC>("MAC", python::init<std::string>()) - .add_property("output_length", &Py_MAC::output_length) - .add_property("keylength_min", &Py_MAC::keylength_min) - .add_property("keylength_max", &Py_MAC::keylength_max) - .add_property("keylength_mod", &Py_MAC::keylength_mod) - .add_property("name", &Py_MAC::name) - .def("valid_keylength", &Py_MAC::valid_keylength) - .def("set_key", &Py_MAC::set_key) - .def("clear", &Py_MAC::clear) - .def("update", &Py_MAC::update) - .def("final", &Py_MAC::final); - } diff --git a/wrappers/boost-python/src/pk.cpp b/wrappers/boost-python/src/pk.cpp deleted file mode 100644 index 72d3294b8..000000000 --- a/wrappers/boost-python/src/pk.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/dh.h> -#include <botan/look_pk.h> -using namespace Botan; - -#include <boost/python.hpp> -namespace python = boost::python; - -std::string encode_pub(const Public_Key* key, - const std::string& type) - { - if(type == "DER") - { - Pipe pipe; - pipe.start_msg(); - X509::encode(*key, pipe, RAW_BER); - pipe.end_msg(); - return pipe.read_all_as_string(); - } - else if(type == "PEM") - return X509::PEM_encode(*key); - else - throw Encoding_Error("Unknown key encoding method " + type); - } - -std::string encode_priv(const Private_Key* key, - const std::string& type) - { - if(type == "DER") - { - Pipe pipe; - PKCS8::encode(*key, pipe, RAW_BER); - return pipe.read_all_as_string(); - } - else if(type == "PEM") - return PKCS8::PEM_encode(*key); - else - throw Encoding_Error("Unknown key encoding method " + type); - } - -/* -Private_Key* load_priv(const std::string& file, const std::string& pass) - { - return PKCS8::load_key(file, pass); - } - -Public_Key* load_public(const std::string& file) - { - return X509::load_key(file); - } -*/ - -/* -std::string encrypt_string(const PK_Encryptor* enc, const std::string& in) - { - SecureVector<byte> cipher = enc->encrypt((const byte*)in.data(), in.length()); - return std::string((const char*)cipher.begin(), cipher.size()); - } - -std::string decrypt_string(const PK_Decryptor* dec, const std::string& in) - { - SecureVector<byte> plain = dec->decrypt((const byte*)in.data(), in.length()); - return std::string((const char*)plain.begin(), plain.size()); - } -*/ - -void export_pk() - { - /* - python::def("private_key", load_priv, - python::return_value_policy<python::manage_new_object>()); - python::def("public_key", load_public, - python::return_value_policy<python::manage_new_object>()); - */ - - python::class_<Public_Key, boost::noncopyable> - ("Public_Key", python::no_init) - .add_property("name", &Public_Key::algo_name) - .add_property("max_input_bits", &Public_Key::max_input_bits) - .def("public_key", encode_pub); - - python::class_<PK_Encrypting_Key, python::bases<Public_Key>, boost::noncopyable> - ("PK_Encrypting_Key", python::no_init); - - python::class_<Private_Key, python::bases<Public_Key>, boost::noncopyable> - ("Private_Key", python::no_init) - .def("private_key", encode_priv); - - python::class_<PK_Decrypting_Key, python::bases<Private_Key>, boost::noncopyable> - ("PK_Decrypting_Key", python::no_init); - - python::class_<RSA_PublicKey, python::bases<PK_Encrypting_Key> > - ("RSA_PublicKey", python::no_init); - - python::class_<DSA_PublicKey, python::bases<Public_Key> > - ("DSA_PublicKey", python::no_init); - - /* - python::class_<RSA_PrivateKey, python::bases<RSA_PublicKey, PK_Decrypting_Key> > - ("RSA_PrivateKey", python::init<u32bit>()); - */ - - /* - python::class_<PK_Encryptor, boost::noncopyable> - ("PK_Encryptor", python::no_init) - .def("__init__", - python::make_constructor(get_pk_encryptor, - python::with_custodian_and_ward_postcall<0, 1>())) - .def("max_input", &PK_Encryptor::maximum_input_size) - .def("encrypt", encrypt_string); - */ - - /* - python::class_<PK_Decryptor, boost::noncopyable> - ("PK_Decryptor", python::no_init) - .def("__init__", python::make_constructor(get_pk_decryptor)) - .def("decrypt", decrypt_string); - */ - } diff --git a/wrappers/boost-python/src/stream.cpp b/wrappers/boost-python/src/stream.cpp deleted file mode 100644 index f94bd7fd5..000000000 --- a/wrappers/boost-python/src/stream.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/botan.h> -using namespace Botan; - -#include "python_botan.h" - -class Py_StreamCipher - { - public: - u32bit keylength_min() const { return cipher->MINIMUM_KEYLENGTH; } - u32bit keylength_max() const { return cipher->MAXIMUM_KEYLENGTH; } - u32bit keylength_mod() const { return cipher->KEYLENGTH_MULTIPLE; } - - void set_key(const OctetString& key) { cipher->set_key(key); } - bool valid_keylength(u32bit kl) const - { - return cipher->valid_keylength(kl); - } - - std::string name() const { return cipher->name(); } - void clear() throw() { cipher->clear(); } - - std::string crypt(const std::string& in) const - { - SecureVector<byte> out(in.size()); - cipher->encrypt((const byte*)in.data(), out.begin(), in.size()); - return std::string((const char*)out.begin(), out.size()); - } - - Py_StreamCipher(const std::string& name) - { - cipher = get_stream_cipher(name); - } - ~Py_StreamCipher() { delete cipher; } - private: - StreamCipher* cipher; - }; - -void export_stream_ciphers() - { - python::class_<Py_StreamCipher>("StreamCipher", python::init<std::string>()) - .add_property("keylength_min", &Py_StreamCipher::keylength_min) - .add_property("keylength_max", &Py_StreamCipher::keylength_max) - .add_property("keylength_mod", &Py_StreamCipher::keylength_mod) - .add_property("name", &Py_StreamCipher::name) - .def("clear", &Py_StreamCipher::clear) - .def("valid_keylength", &Py_StreamCipher::valid_keylength) - .def("set_key", &Py_StreamCipher::set_key) - .def("crypt", &Py_StreamCipher::crypt); - } diff --git a/wrappers/swig/Makefile b/wrappers/swig/Makefile deleted file mode 100644 index ff55c793c..000000000 --- a/wrappers/swig/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -LANG=-python -LANG_INC=/usr/include/python2.3 - -CFLAGS=$(shell botan-config --cflags) -LIBS=$(shell botan-config --libs) - -CXX = g++ -g -SWIG = swig -Wall - -all: _botan.so - -_botan.so: base.o pipe.o filter.o botan_wrap.o - $(CXX) -shared $^ $(LIBS) -o $@ - -botan_wrap.cpp: botan.swg base.h - $(SWIG) $(LANG) -c++ -o $@ $< - -botan_wrap.o: botan_wrap.cpp - $(CXX) $(CFLAGS) -I$(LANG_INC) -c $^ -o $@ - -base.o: base.cpp base.h - $(CXX) $(CFLAGS) -c $< -o $@ - -pipe.o: pipe.cpp base.h - $(CXX) $(CFLAGS) -c $< -o $@ - -filter.o: filter.cpp base.h - $(CXX) $(CFLAGS) -c $< -o $@ - -clean: - rm -f *.o _botan.so botan.py botan.pyc - rm -f *_wrap.o *_wrap.cpp diff --git a/wrappers/swig/base.cpp b/wrappers/swig/base.cpp deleted file mode 100644 index 448b3d48e..000000000 --- a/wrappers/swig/base.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/************************************************* -* SWIG Interface for basic Botan interface * -* (C) 1999-2003 Jack Lloyd * -*************************************************/ - -#include "base.h" -#include <botan/init.h> - -#include <stdio.h> - -/************************************************* -* Initialize the library * -*************************************************/ -LibraryInitializer::LibraryInitializer(const char* args) - { - Botan::Init::initialize(args); - } - -/************************************************* -* Shut down the library * -*************************************************/ -LibraryInitializer::~LibraryInitializer() - { - Botan::Init::deinitialize(); - } - -/************************************************* -* Create a SymmetricKey * -*************************************************/ -SymmetricKey::SymmetricKey(const std::string& str) - { - key = new Botan::SymmetricKey(str); - printf("STR CON: %p %p\n", this, key); - } - -/************************************************* -* Create a SymmetricKey * -*************************************************/ -SymmetricKey::SymmetricKey(u32bit n) - { - key = new Botan::SymmetricKey(n); - printf("N CON: %p %p\n", this, key); - } - -/************************************************* -* Destroy a SymmetricKey * -*************************************************/ -SymmetricKey::~SymmetricKey() - { - printf("DESTR: %p %p\n", this, key); - delete key; - key = 0; - //printf("deleted\n"); - } - -/************************************************* -* Create an InitializationVector * -*************************************************/ -InitializationVector::InitializationVector(const std::string& str) : iv(str) - { - } diff --git a/wrappers/swig/base.h b/wrappers/swig/base.h deleted file mode 100644 index 341a5c35a..000000000 --- a/wrappers/swig/base.h +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************* -* SWIG Interface for Botan * -* (C) 1999-2003 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_WRAP_BASE_H__ -#define BOTAN_WRAP_BASE_H__ - -#include <botan/pipe.h> - -#if !defined(SWIG) - #define OUTPUT - #define INOUT -#endif - -/************************************************* -* Typedefs * -*************************************************/ -typedef unsigned char byte; -typedef unsigned int u32bit; - -/************************************************* -* Library Initalization/Shutdown Object * -*************************************************/ -class LibraryInitializer - { - public: - LibraryInitializer(const char*); - ~LibraryInitializer(); - }; - -/************************************************* -* Symmetric Key Object * -*************************************************/ -class SymmetricKey - { - public: - std::string as_string() const { return key->as_string(); } - u32bit length() const { return key->length(); } - SymmetricKey(u32bit = 0); - SymmetricKey(const std::string&); - ~SymmetricKey(); - private: - Botan::SymmetricKey* key; - }; - -/************************************************* -* Initialization Vector Object * -*************************************************/ -class InitializationVector - { - public: - std::string as_string() const { return iv.as_string(); } - u32bit length() const { return iv.length(); } - InitializationVector(u32bit n = 0) { iv.change(n); } - InitializationVector(const std::string&); - private: - Botan::InitializationVector iv; - }; - -/************************************************* -* Filter Object * -*************************************************/ -class Filter - { - public: - Filter(const char*); - //Filter(const char*, const SymmetricKey&); - //Filter(const char*, const SymmetricKey&, const InitializationVector&); - ~Filter(); - private: - friend class Pipe; - Botan::Filter* filter; - bool pipe_owns; - }; - -/************************************************* -* Pipe Object * -*************************************************/ -class Pipe - { - public: - static const u32bit DEFAULT_MESSAGE = 0xFFFFFFFF; - - void write_file(const char*); - void write_string(const char*); - - u32bit read(byte*, u32bit, u32bit = DEFAULT_MESSAGE); - std::string read_all_as_string(u32bit = DEFAULT_MESSAGE); - - u32bit remaining(u32bit = DEFAULT_MESSAGE); - - void start_msg(); - void end_msg(); - - Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0); - ~Pipe(); - private: - Botan::Pipe* pipe; - }; - -#endif diff --git a/wrappers/swig/botan.swg b/wrappers/swig/botan.swg deleted file mode 100644 index 9088f4272..000000000 --- a/wrappers/swig/botan.swg +++ /dev/null @@ -1,26 +0,0 @@ -/************************************************* -* SWIG Interface for Botan * -*************************************************/ -%module botan - -%include "typemaps.i" -%include "std_string.i" -%include "exception.i" -%include "constraints.i" -%include "carrays.i" - -%{ -#include "base.h" -%} - -%exception { - try { - $action - } - catch(std::exception& e) - { - SWIG_exception(SWIG_RuntimeError, e.what()); - } -} - -%include "base.h" diff --git a/wrappers/swig/doit.py b/wrappers/swig/doit.py deleted file mode 100755 index 98bc97087..000000000 --- a/wrappers/swig/doit.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python2 - -import botan - -def hash_it(hash, input): - f1 = botan.Filter("MD5") - f2 = botan.Filter("Hex_Encoder") - pipe = botan.Pipe(f1, f2) - - pipe.start_msg() - pipe.write_string(input) - pipe.end_msg() - - print pipe.remaining() - - out = pipe.read(0) - - - - -def main: - init = botan.LibraryInitializer - - print hash_it("MD5", "foo") - - - key1 = botan.SymmetricKey("ABCD") - print key1.as_string() - key2 = botan.SymmetricKey(16) - print key2.as_string() - - iv1 = botan.InitializationVector(8) - print iv1.as_string() - - - f3 = pipe.read(pipe.remaining()) - - size = pipe.remaining() - out = botan.byte_array(size) - pipe.read(out.cast,size) - - for i in range (0,size): - print "%02X" % out[i] - - print pipe.read_all_as_string() - -if __name__ == "__main__": - sys.exit(main()) - diff --git a/wrappers/swig/filter.cpp b/wrappers/swig/filter.cpp deleted file mode 100644 index 53ff0e6a3..000000000 --- a/wrappers/swig/filter.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/************************************************* -* SWIG Interface for Filter Retrieval * -* (C) 1999-2003 Jack Lloyd * -*************************************************/ - -#include "base.h" -#include <botan/lookup.h> -#include <botan/filters.h> - -/************************************************* -* Filter Creation * -*************************************************/ -Filter::Filter(const char* filt_string) - { - filter = 0; - pipe_owns = false; - - /* - Fixme: This is all so totally wrong. It needs to have full argument - processing for everything, all that kind of crap. - */ - const std::string filt_name = filt_string; - - if(Botan::have_hash(filt_name)) - filter = new Botan::Hash_Filter(filt_name); - else if(filt_name == "Hex_Encoder") - filter = new Botan::Hex_Encoder; - } - -/************************************************* -* Filter Destruction * -*************************************************/ -Filter::~Filter() - { - /* - if(!pipe_owns) - delete filter; - */ - } diff --git a/wrappers/swig/pipe.cpp b/wrappers/swig/pipe.cpp deleted file mode 100644 index 0f35d5a43..000000000 --- a/wrappers/swig/pipe.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************* -* SWIG Interface for Botan Pipe API * -* (C) 1999-2003 Jack Lloyd * -*************************************************/ - -#include "base.h" -#include <botan/pipe.h> - -#include <stdio.h> - -/************************************************* -* Write the contents of a file into a Pipe * -*************************************************/ -void Pipe::write_file(const char* filename) - { - Botan::DataSource_Stream in(filename); - pipe->write(in); - } - -/************************************************* -* Write the contents of a string into a Pipe * -*************************************************/ -void Pipe::write_string(const char* string) - { - pipe->write(string); - } - -/************************************************* -* Read the contents of a Pipe into a buffer * -*************************************************/ -u32bit Pipe::read(byte* buf, u32bit length, u32bit msg) - { - printf("read %p %d\n", buf, length); - return 0; - //return pipe->read(buf, length, msg); - } - -/************************************************* -* Read the contents of a Pipe as a string * -*************************************************/ -std::string Pipe::read_all_as_string(u32bit msg) - { - return pipe->read_all_as_string(msg); - } - -/************************************************* -* Find out how much stuff the Pipe still has * -*************************************************/ -u32bit Pipe::remaining(u32bit msg) - { - return pipe->remaining(); - } - -/************************************************* -* Start a new message * -*************************************************/ -void Pipe::start_msg() - { - pipe->start_msg(); - } - -/************************************************* -* End the current msessage * -*************************************************/ -void Pipe::end_msg() - { - pipe->end_msg(); - } - -/************************************************* -* Create a new Pipe * -*************************************************/ -Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) - { - pipe = new Botan::Pipe(); - - if(f1) { pipe->append(f1->filter); f1->pipe_owns = true; } - if(f2) { pipe->append(f2->filter); f2->pipe_owns = true; } - if(f3) { pipe->append(f3->filter); f3->pipe_owns = true; } - if(f4) { pipe->append(f4->filter); f4->pipe_owns = true; } - } - -/************************************************* -* Destroy this Pipe * -*************************************************/ -Pipe::~Pipe() - { - delete pipe; - } diff --git a/wrappers/swig/pk.swg b/wrappers/swig/pk.swg deleted file mode 100644 index 8e03cf120..000000000 --- a/wrappers/swig/pk.swg +++ /dev/null @@ -1,8 +0,0 @@ -%module botan - -%{ -#undef ANY -#include "botan/pubkey.h" -%} - -%include "botan/pubkey.h" diff --git a/wrappers/swig/readme.txt b/wrappers/swig/readme.txt deleted file mode 100644 index a9965d914..000000000 --- a/wrappers/swig/readme.txt +++ /dev/null @@ -1,34 +0,0 @@ -This is the beginning of an attempt to SWIG-ify Botan so it can be accessed by -other languages. You should use the latest SWIG 1.3 release (I am currently -using SWIG 1.3.19). Currently I am only testing this code with Python 2.2.1, -since that is the language I am mainly interested in at this point. Feel free -to send me patches so this is usable with Perl or whatever. - -I'm not attempting to make everything in Botan usable from a script - -basically, I just want the parts that *I* want to use. Most things are not -supported yet, and there are lots of bugs in the stuff that does exist. If -there is something in particular that you would like to be able to use from a -script, let me know (patches are good, too). - -Todo: - * Why does it seg fault if we don't create a LibraryInitializer. It should - throw an exception, like it does in C++. Maybe have it init Botan when the - module is loaded? That seems a lot cleaner/nicer, but I don't know how to - do it yet. - * Lots of problems with exceptions - * Use constraints to prevent bad args when possible - * Pipe/Filter - - Better argument processing for all filters - - Support for ciphers, MACs, etc - - Chain + Fork - - Support for append/prepend/pop/reset in Pipe? - * Public Key Crypto - - RSA - - DSA - - DH - - Generic X.509 and PKCS #8 stuff - * PKI - - X.509 certs + CRLs - - PKCS #10 requests - - X.509 stores - - X.509 CA diff --git a/wrappers/swig/tests/block.py b/wrappers/swig/tests/block.py deleted file mode 100644 index 593937c81..000000000 --- a/wrappers/swig/tests/block.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/python - -import botan, base64 - -class MyCipher(botan.BlockCipher): - def __init__(self): - botan.BlockCipher.__init__(self, 16, 16, 32, 8) - def encrypt(self, val): - print "encrypt", val - return val.swapcase() - def decrypt(self, val): - print "decrypt", val - return val.swapcase() - def set_key(self, key): - print "set_key", key - def clone(self): - print "cloning" - return MyCipher() - def name(self): - print "naming" - return "MyCipher" - -cipher = botan.BlockCipher("AES-128") - -print cipher.block_size -print cipher.keylength_min -print cipher.keylength_max -print cipher.keylength_mod -print cipher.name() - -for kl in range(1, 128): - if cipher.valid_keylength(kl): - print "1", - else: - print "0", -print -key = botan.SymmetricKey(16) - -cipher.set_key(key) -ciphertext = cipher.encrypt("ABCDEFGH12345678") -print base64.b16encode(ciphertext) - -cipher2 = cipher.clone() -cipher2.set_key(key) - -plaintext = cipher2.decrypt(ciphertext) -print plaintext - -botan.get_info(cipher) - -mycipher = MyCipher() -botan.get_info(mycipher) diff --git a/wrappers/swig/tests/block2.py b/wrappers/swig/tests/block2.py deleted file mode 100644 index 5faccaf9a..000000000 --- a/wrappers/swig/tests/block2.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python - -import botan, base64 - -class MyCipher(botan.BlockCipherImpl): - def __init__(self): - botan.BlockCipherImpl.__init__(self, 8, 8, 16, 1) - - def name(self): - return "MyCipher" - - def encrypt(self, input): - return input.swapcase() - - def decrypt(self, input): - return input.swapcase() - - def set_key(self, key): - print "Got key",key - -def test(cipher): - print - print cipher - print "Testing", cipher.name() - print cipher.block_size - print cipher.keylength_min, cipher.keylength_max, cipher.keylength_mod - for i in range(1, 64): - if cipher.valid_keylength(i): - print "1", - else: - print "0", - print - cipher.set_key(botan.SymmetricKey(16)) - ciphertext = cipher.encrypt("aBcDeFgH" * (cipher.block_size / 8)) - print repr(ciphertext) - print cipher.decrypt(ciphertext) - -def main(): - test(botan.BlockCipher("Blowfish")) - test(MyCipher()) - test(botan.BlockCipher("AES")) - -if __name__ == "__main__": - main() diff --git a/wrappers/swig/tests/encrypt.py b/wrappers/swig/tests/encrypt.py deleted file mode 100644 index 9896777d4..000000000 --- a/wrappers/swig/tests/encrypt.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python - -import sys, botan - -def encrypt(input): - cipher_key = botan.SymmetricKey("AABB") - print cipher_key.length - cipher_key = botan.SymmetricKey("AABBCCDD") - print cipher_key.length - - cipher = botan.Filter("ARC4", key = cipher_key) - - pipe = botan.Pipe(cipher, botan.Filter("Hex_Encoder")) - - pipe.start_msg() - pipe.write(input) - pipe.end_msg() - - str = pipe.read_all() - print str - return str - -def decrypt(input): - pipe = botan.Pipe(botan.Filter("Hex_Decoder"), - botan.Filter("ARC4", - key = botan.SymmetricKey("AABBCCDD"))) - - pipe.process_msg(input) - return pipe.read_all() - -def main(): - ciphertext = encrypt("hi chappy") - print ciphertext - print decrypt(ciphertext) - -if __name__ == "__main__": - sys.exit(main()) diff --git a/wrappers/swig/tests/filter.py b/wrappers/swig/tests/filter.py deleted file mode 100644 index 2b65d9ff2..000000000 --- a/wrappers/swig/tests/filter.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python - -import sys, botan - -class MyFilter(botan.FilterObj): - def write(self, input): - print "MyFilter::write",input - self.send(input) - def start_msg(self): - print "MyFilter::start_msg" - def end_msg(self): - print "MyFilter::end_msg" - def __del__(self): - print "~MyFilter" - -def main(): - filter = MyFilter() - - pipe = botan.Pipe(botan.Filter("Hex_Encoder"), filter, - botan.Filter("Hex_Decoder")) - pipe.start_msg() - pipe.write("hi chappy") - pipe.end_msg() - print pipe.read_all() - -if __name__ == "__main__": - sys.exit(main()) diff --git a/wrappers/swig/tests/hash.py b/wrappers/swig/tests/hash.py deleted file mode 100644 index 930b8c81a..000000000 --- a/wrappers/swig/tests/hash.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/python - -import botan, base64, md5 - -class PyMD5(botan.HashFunctionImpl): - def name(self): - return "PyMD5" - def update(self, input): - self.md5.update(input) - def final(self): - output = self.md5.digest() - self.md5 = md5.new() - return output - def __init__(self): - botan.HashFunctionImpl.__init__(self, 16, 64) - self.md5 = md5.new() - -hash = botan.HashFunction("SHA-256") - -print hash.name() -print hash.digest_size - -hash.update("hi") -hash.update(" ") -hash.update("chappy") -print base64.b16encode(hash.final()) - -hash2 = PyMD5() -hash2.update("hi chappy") -print base64.b16encode(hash2.final()) diff --git a/wrappers/swig/tests/mac.py b/wrappers/swig/tests/mac.py deleted file mode 100644 index 6110b6102..000000000 --- a/wrappers/swig/tests/mac.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/python - -import botan, base64 - -mac = botan.MAC("HMAC(SHA-512)") - -print mac.name -print mac.output_length - -mac.set_key(botan.SymmetricKey("abcd")) -mac.update("hi chappy") -print base64.b16encode(mac.final()) diff --git a/wrappers/swig/tests/pubkey.py b/wrappers/swig/tests/pubkey.py deleted file mode 100644 index 456c52069..000000000 --- a/wrappers/swig/tests/pubkey.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/python - -import botan - -key = botan.X509_PublicKey("rsapub.pem") -print key -print key.key_id() -print key.max_input_bits -print key.algo -print key.oid diff --git a/wrappers/swig/tests/stream.py b/wrappers/swig/tests/stream.py deleted file mode 100644 index 59d3ffa16..000000000 --- a/wrappers/swig/tests/stream.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/python - -import botan, base64 - -cipher = botan.StreamCipher("ARC4") - -print cipher.name - -key = botan.SymmetricKey(16) - -cipher.set_key(key) -ciphertext = cipher.crypt("hi chappy") - -cipher.set_key(key) -plaintext = cipher.crypt(ciphertext) - -print plaintext diff --git a/wrappers/swig/x509.swg b/wrappers/swig/x509.swg deleted file mode 100644 index 736d3a385..000000000 --- a/wrappers/swig/x509.swg +++ /dev/null @@ -1,9 +0,0 @@ -%module botan - -class X509_Certificate - { - public: - - - private: - }; |