diff options
159 files changed, 5112 insertions, 1835 deletions
diff --git a/Attic/mutex/pthreads/info.txt b/Attic/mutex/pthreads/info.txt index 88de70de0..f135dea48 100644 --- a/Attic/mutex/pthreads/info.txt +++ b/Attic/mutex/pthreads/info.txt @@ -10,7 +10,7 @@ mux_pthr.h </add> <libs> -all!qnx,freebsd,openbsd,netbsd -> pthread +all!qnx,freebsd,dragonfly,openbsd,netbsd -> pthread </libs> <os> @@ -18,6 +18,7 @@ aix cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/checks/algos.cpp b/checks/algos.cpp index 2edaaf14c..dff903e21 100644 --- a/checks/algos.cpp +++ b/checks/algos.cpp @@ -62,6 +62,8 @@ std::vector<algorithm> get_algos() "AES-128/CTR-BE", 16, 16)); algos.push_back(algorithm("Cipher Mode", "AES-128/EAX", 16, 16)); algos.push_back(algorithm("Cipher Mode", "AES-128/XTS", 32, 16)); + algos.push_back(algorithm("Cipher Mode", "Serpent/CTR", + "Serpent/CTR-BE", 32, 16)); algos.push_back(algorithm("Stream Cipher", "ARC4", 16)); algos.push_back(algorithm("Stream Cipher", "Salsa20", 32)); diff --git a/checks/bench.cpp b/checks/bench.cpp index 6df7319c0..1610bed1e 100644 --- a/checks/bench.cpp +++ b/checks/bench.cpp @@ -27,7 +27,7 @@ namespace { double bench_filter(std::string name, Botan::Filter* filter, Botan::RandomNumberGenerator& rng, - bool html, double seconds) + double seconds) { Botan::Pipe pipe(filter, new BitBucket); @@ -52,27 +52,13 @@ double bench_filter(std::string name, Botan::Filter* filter, std::cout.setf(std::ios::fixed, std::ios::floatfield); std::cout.precision(2); - if(html) - { - if(name.find("<") != std::string::npos) - name.replace(name.find("<"), 1, "<"); - 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 - { - std::cout << name << ": " << std::string(25 - name.length(), ' '); - std::cout.width(6); - std::cout << mbytes_per_sec << " MiB/sec" << std::endl; - } + std::cout << name << " " << std::string(25 - name.length(), ' '); + std::cout.width(6); + std::cout << mbytes_per_sec << " MiB/sec" << std::endl; return (mbytes_per_sec); } -double bench(const std::string& name, const std::string& filtername, bool html, +double bench(const std::string& name, const std::string& filtername, double seconds, u32bit keylen, u32bit ivlen, Botan::RandomNumberGenerator& rng) { @@ -88,7 +74,7 @@ double bench(const std::string& name, const std::string& filtername, bool html, Botan::Filter* filter = lookup(filtername, params); if(filter) - return bench_filter(name, filter, rng, html, seconds); + return bench_filter(name, filter, rng, seconds); return 0; } @@ -96,23 +82,9 @@ double bench(const std::string& name, const std::string& filtername, bool html, void benchmark(const std::string& what, Botan::RandomNumberGenerator& rng, - bool html, double seconds) + double seconds) { try { - if(html) - { - std::cout << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD " - << "HTML 4.0 Transitional//EN\">\n" - << "<HTML>\n\n" - << "<TITLE>Botan Benchmarks</TITLE>\n\n" - << "<BODY>\n\n" - << "<P><TABLE BORDER CELLSPACING=1>\n" - << "<THEAD>\n" - << "<TR><TH>Algorithm " - << "<TH>Mib / second\n" - << "<TBODY>\n"; - } - double sum = 0; u32bit how_many = 0; @@ -122,26 +94,18 @@ void benchmark(const std::string& what, if(what == "All" || what == algos[j].type) { double speed = bench(algos[j].name, algos[j].filtername, - html, seconds, algos[j].keylen, + seconds, algos[j].keylen, algos[j].ivlen, rng); if(speed > .00001) /* log(0) == -inf -> messed up average */ sum += std::log(speed); how_many++; } - if(html) - std::cout << "</TABLE>\n\n"; - double average = std::exp(sum / static_cast<double>(how_many)); - if(what == "All" && html) - std::cout << "\n<P>Overall speed average: " << average - << "\n\n"; - else if(what == "All") + if(what == "All") std::cout << "\nOverall speed average: " << average << std::endl; - - if(html) std::cout << "</BODY></HTML>\n"; } catch(Botan::Exception& e) { @@ -172,7 +136,7 @@ u32bit bench_algo(const std::string& name, { if(algos[j].name == name) { - bench(algos[j].name, algos[j].filtername, false, seconds, + bench(algos[j].name, algos[j].filtername, seconds, algos[j].keylen, algos[j].ivlen, rng); return 1; } diff --git a/checks/bench.h b/checks/bench.h index 07d67e0d1..0cc3f46d1 100644 --- a/checks/bench.h +++ b/checks/bench.h @@ -25,10 +25,10 @@ class Benchmark_Report void benchmark(const std::string&, Botan::RandomNumberGenerator&, - bool html, double seconds); + double seconds); void bench_pk(Botan::RandomNumberGenerator&, - const std::string&, bool html, double seconds); + const std::string&, double seconds); u32bit bench_algo(const std::string&, Botan::RandomNumberGenerator&, diff --git a/checks/check.cpp b/checks/check.cpp index 678cf4b09..30ee90d98 100644 --- a/checks/check.cpp +++ b/checks/check.cpp @@ -94,7 +94,7 @@ int main(int argc, char* argv[]) { try { - OptionParser opts("help|html|test|validate|" + OptionParser opts("help|test|validate|" "benchmark|bench-type=|bench-algo=|seconds="); opts.parse(argv); @@ -113,7 +113,6 @@ int main(int argc, char* argv[]) << " --benchmark: Benchmark everything\n" << " --bench-type={block,mode,stream,hash,mac,rng,pk}:\n" << " Benchmark only algorithms of a particular type\n" - << " --html: Produce HTML output for benchmarks\n" << " --seconds=n: Benchmark for n seconds\n" << " --init=<str>: Pass <str> to the library\n" << " --help: Print this message\n"; @@ -140,11 +139,9 @@ int main(int argc, char* argv[]) } } - const bool html = opts.is_set("html"); - if(opts.is_set("benchmark")) { - benchmark("All", rng, html, seconds); + benchmark("All", rng, seconds); } else if(opts.is_set("bench-algo")) { @@ -156,7 +153,7 @@ int main(int argc, char* argv[]) const std::string alg = algs[j]; u32bit found = bench_algo(alg, rng, seconds); if(!found) // maybe it's a PK algorithm - bench_pk(rng, alg, html, seconds); + bench_pk(rng, alg, seconds); } } else if(opts.is_set("bench-type")) @@ -164,21 +161,21 @@ int main(int argc, char* argv[]) const std::string type = opts.value("bench-type"); if(type == "all") - benchmark("All", rng, html, seconds); + benchmark("All", rng, seconds); else if(type == "block") - benchmark("Block Cipher", rng, html, seconds); + benchmark("Block Cipher", rng, seconds); else if(type == "stream") - benchmark("Stream Cipher", rng, html, seconds); + benchmark("Stream Cipher", rng, seconds); else if(type == "hash") - benchmark("Hash", rng, html, seconds); + benchmark("Hash", rng, seconds); else if(type == "mode") - benchmark("Cipher Mode", rng, html, seconds); + benchmark("Cipher Mode", rng, seconds); else if(type == "mac") - benchmark("MAC", rng, html, seconds); + benchmark("MAC", rng, seconds); else if(type == "rng") - benchmark("RNG", rng, html, seconds); + benchmark("RNG", rng, seconds); else if(type == "pk") - bench_pk(rng, "All", html, seconds); + bench_pk(rng, "All", seconds); else std::cerr << "Unknown --bench-type " << type << "\n"; } diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index 8e5054a9a..f99a13a93 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -603,7 +603,7 @@ void benchmark_elg(RandomNumberGenerator& rng, } void bench_pk(RandomNumberGenerator& rng, - const std::string& algo, bool, double seconds) + const std::string& algo, double seconds) { /* There is some strangeness going on here. It looks like algorithms @@ -675,6 +675,8 @@ void bench_pk(RandomNumberGenerator& rng, benchmark_dsa_nr<NR_PrivateKey>(rng, seconds, report); #endif +#if defined(BOTAN_HAS_RW) if(algo == "All" || algo == "RW") benchmark_rw(rng, seconds, report); +#endif } diff --git a/checks/validate.dat b/checks/validate.dat index 05a9b98bb..287c068b6 100644 --- a/checks/validate.dat +++ b/checks/validate.dat @@ -19472,7 +19472,20 @@ D261D6041824D259290EABD3E9132DB8:7E3B14847526572FF2AA5D7BD626B560:\ 01000000000000000000000000000000:07E5E5AD7097B849BADC2D5D803B7F6A:\ 0000000000000000000000000000000000000000000000000000000000000000 +1032547698BADCFEEFCDAB8967452301:D5BAA00A4BB9D8A7C981C8DC90D89D92:\ +FFEEDDCCBBAA99887766554433221100 +145F0B8B663176B95DCAB7E9DCD5CC24:1032547698BADCFEEFCDAB8967452301:\ +FFEEDDCCBBAA99887766554433221100 + +1032547698BADCFEEFCDAB8967452301:DA860842B720802BF404A4C71034879A:\ +8899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100 + +B2696BD0D98C17953E4239225D27202C:1032547698BADCFEEFCDAB8967452301:\ +8899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100 + +1032547698BADCFEEFCDAB8967452301:93DF9A3CAFE387BD999EEBE393A17FCA:\ +00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100 # Corrected test vectors, based on NIST's clarification of May 9, 2002 [Skipjack] @@ -22938,6 +22951,51 @@ B4ECC305C3DBD8E5:FBBEC8F5DBF4CEFD:1B5E23EBD915C1FEE59F57DD91AF7347 # The block cipher tests above are distinct from these ECB mode tests # for testing reasons. They could otherwise easily be CIPHER/ECB/NoPadding + +[AES/ECB/NoPadding] +D8F532538289EF7D06B506A4FD5BE9C9FD7A929E0FD917686D9520ED236A276D\ +69E63C821F9DE0BF23CF1D19C7374FD1C3139DE2E1BA4693C3E9D29D774C2FF4\ +69E63C821F9DE0BF23CF1D19C7374FD1C3139DE2E1BA4693C3E9D29D774C2FF4\ +D8F532538289EF7D06B506A4FD5BE9C9FD7A929E0FD917686D9520ED236A276D\ +D8F532538289EF7D06B506A4FD5BE9C9C3139DE2E1BA4693C3E9D29D774C2FF4:\ +FD7A929E0FD917686D9520ED236A276D69E63C821F9DE0BF23CF1D19C7374FD1\ +C3139DE2E1BA4693C3E9D29D774C2FF46BA2DCF84C0E7E4D75CB53AD11BA76D6\ +C3139DE2E1BA4693C3E9D29D774C2FF46BA2DCF84C0E7E4D75CB53AD11BA76D6\ +FD7A929E0FD917686D9520ED236A276D69E63C821F9DE0BF23CF1D19C7374FD1\ +FD7A929E0FD917686D9520ED236A276D6BA2DCF84C0E7E4D75CB53AD11BA76D6:\ +00010203050607080A0B0C0D0F101112 + +[Serpent/ECB/NoPadding] +D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78E\ +D29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78E\ +D29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78E\ +D29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78E\ +D29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871\ +D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871\ +D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871\ +D29D576F315C5C58126F660D6D8C28712D62A890315C5C58126F660D6D8C2871\ +AA26D561F567520E8AE47528C24C18D731A2193D9A97FED6922B17AAA6372B74\ +BE5DEBD559E303C9C92B174A5107BBFEB626D8F65EDCCDF3AEE475C8A1837722\ +41DDE7C1F1631F5FDED4F42746471BD651D238BA86176EFE39E4695AAEB73B52\ +EA5926CADAD8018962E469BA920CB8BF1EA9062E4D9CEDD5FAD4F4C7990367A4\ +B966E5C5D2277288C61B96A559CC84AFB6A6583C5AACFCD6212B0BD8AEF3C6A9\ +A11DDBD175639341052B0B384678D8D9352299B71DD880E29D1B96452DB86540:\ +B2288B968AE8B08648D1CE9606FD992D717EB02EB81A2E939D54ACA91087112D\ +0D809C5EE82F477EBA7B956DBB23463B0F0190D616F5294112FFB7884E8B37F9\ +41BA1B505386B7428B88338188F7E718A3348230BF5CFA552F88D22463D9703A\ +115351622E016BCA26918D17E13225F67EE4E3F2C46FE52ECBDA044C585717DC\ +563A8403FF5309D62370B1DCF5A11EDD2F7D73602B70CD2553E44C1D3F170126\ +155BBD9BE3A965B345E834718F651CEF6CC65E8C5C566E894817350F497816F1\ +EEFA51FC91FEBB6E9F8CB141CC0EB6AF3C6F8380CBD3C996167F2F0E90E71B75\ +6C87EB62A4975356B28DCBF6A64A0BD107206D48FE6DBE19D50314B90AC87B83\ +35706F9B26007071AD8105CFAA1C1E2FF7FEAE5CEC4D11477F24E6B200906870\ +3C0E29E2950F2AC2DACD63DEEB5C7EFA9FDB9F3B740563D5518287DC981FC9CB\ +46D4B5A5A86FEC08FE70D18297DCF51072DDBE038DA040EBB12C509F5940A212\ +DDEB59F02132BE4581FC23EABAA960D6341D9352E36DFD6E4EAF0F6F439BC8CE\ +73A9AB3164FF30350F2DC08E939A104D6DF0C2C28F8E2D44468A61278BB6B429\ +4DAE45AE0CAA032FC97CD4D8C57FB83BBA8AFCAE22070BC882D3A42B38A09E65:\ +00000000000000000000000000000000 + [DES/ECB/NoPadding] 059B5E0851CF143A:86A560F10EC6D85B:0113B970FD34F2CE 4E6F772069732074:3FA40E8A984D4815:0123456789ABCDEF @@ -24214,6 +24272,1007 @@ D05BC090A8E04F1B3D3ECDD5BAEC0FD4EDBF9DACE45D6F6A7306E64BE5DD82:\ FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0BFBEBDBCBBBAB9B8B7B6B5B4B3B2B1B0:\ 9A785634120000000000000000000000 +[Serpent/CTR-BE] +F3:3A:\ +740614949B42870F0851A0D639A37AC8288898B0F9CC3B326B983ADA69BDBB76:\ +3377FFD0C8093067A0E33B8700E2C2E1 + +3018:053E:\ +872BCAEFB1985B9C10B1F2DE2790E22CF31C362AC7276D437D0DD697F1682BC4:\ +53C8B7C9BA119E81AC5474FB70BF82FB + +C503C6:DC4178:\ +DE3317D05233577D476509E638486ED2ABE26ABFD847C13A8AAB189F322F46B8:\ +47D690C680A567B9942BBD0A2700B884 + +FC9B1F9C:89FC80B9:\ +A2B4D60F8F9B35C56168D80E8828F3931A5BDA190E65B9B06A814277DB2B4F63:\ +B3B98D928D3EBE1B9E07B291ACF9CD2A + +F1CDFB642B:2BEBCA6F33:\ +E39D7D09F410CDC21333D8EBE5E33E7A2E24872A99254AEDAFFC633061C32EE6:\ +107FA9631083DE98F5C72A383F541F3E + +9C3BACCD6154:DE9920471C92:\ +9F7268895714AFE229162D50CA59F1273744BDC28B198E1685F4323AFAE1243D:\ +68C5EEB64FC3DE106B99C0896CC0689E + +B5602241E6ACAF:2FD52D0292019C:\ +27757554DD1B5BE2E660576FBAEB238A0F7642F9A65771B69AF276A57FC04354:\ +9BB3DB1661C90DE853294D20A369B999 + +8E27C11E30E23C5F:0294FE7CC3F020FB:\ +84688112BE481C65B282D4DF9A953526AEBF05FDD2F3D84E7C32830E3BC185C8:\ +3ABFC6E1B2358A3B968E416B9087BBD9 + +A4CC3F182076E93409:00EE68EB6CC635BCFB:\ +967BA8A79CCD302B294E519813B72EB5C4D24BD86322FBDE08C292C2DC4723E8:\ +D7DB3A2BC532D1F1685CB612FBCF33A1 + +25B63E2B38DFF81FA490:E75F1A6DF39CC7A76D12:\ +6757B7CA6D7EEBFD0E679E18CB30D16ACC71D0B1A149DA27E439DA1BA0BA37C9:\ +3199830075CB5E87016EEAE5B0B26F13 + +310605508E614C101E829B:366A5DCEB8E76183C95CFC:\ +F92107A1778C99C45B4E229567BF5CCAB2C5B1204052B8720161AEDCCF57E36F:\ +378D5BF003FB48A4D183D5227151FE11 + +6A706D5F6526ED4AAEE00D7D:8145258ED5FE88C34E671101:\ +F892DD670B66CCF6B8E458A6F068FBA79F4A69AE3A028E43D8E219BE940BB826:\ +08BA9435AF764BE0E44515FF72D6DCBD + +FE62E34899D4115DF7FFF51A8A:66F68C5AEC9A4BB123056667D9:\ +BCE52007E10A2CF3077D00225C95F2D68FCDF380AC17304553FBC1DA10117B15:\ +3FFED78824BEB8D6D655CC80190124BE + +191D3CFE172BEFAC1A8A428DF951:7CE0D419C43342FD2CD8D56685BF:\ +534A1F49FCD2D99E2ED2F094E170809091195EDEA2ED94EA4DEE64F9A6F89E05:\ +D98E8D86E9BE95318429FD7286D528E5 + +2C92024B2587851C0F58C91B822DF6:36FAB117335A5F0C619826ED801670:\ +41422F58E73BE8C494D750910CA612B2FDA0A41D041ADDDAB4144DF30CE7B26B:\ +DF0771CEB11F1BAF934289FA42F54319 + +0CC08B6ED36673C0591901E14AEF4792:250C9E812F38A9192CC65C6EE5B9DB60:\ +EDA2AFF3C4923D3CE745EB78655B0D27DBDB5C584AFE56564C7B625903CED927:\ +95C67856E6EB7B0E98F0934A47DF6485 + +C6B6E1F1BC46E8377F6C397C136461973F:AA0C36B960BFC811185F74D22356686414:\ +D4FBFD37C5B9D12E5E43D1867E1692A2B331CAC9E6C46C228A45E95AFA303185:\ +30B9693B12B7F48C1C07F1441706821D + +CF1DAFB2581C47D06D8F178787729F8FF457:\ +10510051990A826CFFDF9014CA0B49481E39:\ +47E9CA81E014F6AA4F94A7C0B8A533B7A636FF14E76935D9C7A3CB01E3AD64E9:\ +DEE733BD4644E258CF98F7FE87AD8E5A + +EB95043E36EFDF2B5FB8F17B6806B2B021D1DD:\ +A739171DAE7EC95CEB492183803D37165D1A79:\ +6BBA2F42B85C58A4916F618A294553E084E223739F575159DE9EC4F5A63F3AAB:\ +0DCA755F625F78C363AC7EAB801DD471 + +3277ADC7055990FDA21C89F183F0A380E71B696D:\ +610369449E344D609EEB89210AFFD1C90B05C197:\ +F3702792DEFB775F10B142CAA78D05DB26A4A8061CEB39FA2B4A27106DE8D9DF:\ +5C8EF39AE0EDAEB76CF3C10B94D1A002 + +43733C60414C054EACF68F85C67D547AFD0003AABA:\ +E8F7CCA960B713991BEF20DEB3DF284ECFE912B479:\ +AAE83136AB1EC19B3BC892B0B5E8EC7A6E20FF5AC6C126DAF6189A7E2E344AF0:\ +C99EBDE92D57326A37B4B6F2C19363FD + +E2ACCDA4075886B085C7A7B71E39BD23F71DD16BC4E1:\ +7A0552BA9DBCE00A60AB31F8D0E590D79E2EBFC49713:\ +222373452D105C2F58E87F5DDDF07FE464E47BC8309718FB30674770CA24FD34:\ +A03B629DB1C399F8EE32A7C08C0FDDB3 + +33CF3C69194FBBD03B0496F1982C570B363DDE621303AE:\ +8D2763FAD25E2A3BA7F4EE3ADA3CC05310B453734EEC56:\ +CCD9F95EB29B2609CB35C959009B56FD43A60B4353A2F3D60FE78F2219074330:\ +884C24E8368B3DB123F47D03F3812F12 + +32DE0A03F6D52AA26BEECF4AB22ABF3A49768683F86EA983:\ +D4EE5E9BD04A09D73DFA9752A8DFAD00F151E822052B500B:\ +F7C88B964D55E40A04D8016900A3449015D6324DE16A024C0F9FBB1DE505C1AC:\ +308E6F85EE34ECE3C70C1EE2CB7E6777 + +52F14AAE8ADB041BAC458EF07FA247FE50B868888089587933:\ +BE61DB06D28CA4D3B418F10F463FC42EA254929C5C87D35418:\ +972C448AA251ACA8F589BE0F5793100D14EE3282DFB321CE5943FDE99D1F31AE:\ +11C202F46DC54AEDFBB543C3A55E7DB8 + +E56DFAD59ECA41C38A68C64388CA4D2CF94B319C65E033C26A8C:\ +DC4A5B96090CC569B623D54BB1DAA4A7B6D879F21BA420D80637:\ +DFFBD3EA5DB1F4D7D9613F069BAF8737F0E37A33BAC9A9AE2EC67FF20E37442D:\ +17E670BC9C590D7B320A233232D43311 + +A89CF708448D7D4B1BD8C252F9EF7A0A7D978A1E862713F807E0FD:\ +A244860FB2E83D608B25D77ED4EBBCAA7C2AF886708002C77EB5F5:\ +A14BB231478EBDBD7B6A7D7039559099AAA281D25D095F286B8104DF77DE0C8A:\ +5410153016A90F03A3863EC58BD66004 + +BA6C11D80E304AFD1D922E2B35A47C3ACB34F7DCB7826F76A3C469EA:\ +CE19CF171B181B3CC5261B5A38E9142DA7479F88A9B0F7F63E98BD7A:\ +B5C0F5A46D855F6CE47CAC0198FCAFB7432AF8810A3746A90CB440DC2AA1CC9C:\ +A1A57176001EF2B0417FB7DE1630AB54 + +90D97D574AFA947AD194F3B94D17D83073D6ECF2FDBDD5CEE09D3D553C:\ +5139448ECB4D8B454563FF5BC6CA47D9BD23329E772F03E4C661E4CFA7:\ +D684575372F4EC2F0131D786EF6B9666C38D2E99C2DAB7ADBD1C9FC805DA4229:\ +81301A434C73C64DDB94440FC887542E + +F4C312864C4FF38BA8D285608FC924DE8E60F4FF0E603AC7D3548CBCE1AA:\ +04823EE2C43AE04312C6F538F03DB4635D13026D546254A1E0BF5AF97B58:\ +7C3F63710A6B10B0131C5BF96BCEEF6AD226FC25880A975E355CC2547435D861:\ +B3F1E356BDCB368C8F1D306DAFF59684 + +9F188A9CC6957F8408FF2A93AECEABEC0D6484AAD13C88060CFA7C52F55130:\ +FA96B9A0FAA199FF22357287FA8DB515ED3D522039C3FA649E5BBFDE5D0D79:\ +8C263F3C683F2C78E8607AC7E79C703F0F1D872BFFADB07CBB9E07C62624291E:\ +1BED13CCADDA5A02EE6F3F529A7A97A0 + +6F129CDB56D48914EFAE7A534C33D03280CF30D12389EB5119106790B84BD73D:\ +29ED54DFD26F097312C42848BD496B78436F907238EC8DBDB5A22FFD76CE76D2:\ +69F48BB5EAA67974713FA974EE645B5DA6B8E5665CE0E40347575D050755EA6A:\ +CD6E4DDE0DEDEB87B7BCE9998F41218F + +49407E33C46EAFB24B01BDF5300DEA35AA5BB5AEDAAA2B5E47B2B63753A44F71127F:\ +DC0A9F56FB2F440305B288C1C0CCB896B21D89FC3F741034DD76B6887740C5CD4A20:\ +3AE57D49BAE4C54AFCA650206B3FCBA71306286F1B9A51624CE3CF08B5791CB3:\ +75D84A34073AA6331A8990572C5FF55B + +C34EF208CBE5F148CCF3E005BD2168C8D8346B18464EC8A6C8DD156A3ED34CE35C2A16F2:\ +878A83F17390490E68D50937BEC73D4A5BD4183ACCEB0D582464DD9D3ADE683E830E8C24:\ +F39D1CF76592D48DE487808FBCA14585C15F29FFB7C9EF9A4AF74B1DC29459BF:\ +50FE7E7F598B4FC4D0FF6D256135861A + +6732BDCFAF3C9681E5684208D5C49354C8C221FBB584080639E3A66C0CEFEE4662BCB787\ +FFD2:\ +2B40579DD8E87440DCBC664920573309D3342DB52463F76FC7BDDA45861F8775553129F9\ +48D6:\ +8B387194C2E79916F5D2B5E3145B4F7CBDF8190EEBD05B598A3F44D1480FE045:\ +6C7EAE05E72898C271A3D7F1668532FA + +3CC7B907609C374805F3E0625C2A8B77BBFE8C22860F749E4871541D27BE589B21773489\ +E08EBFC5:\ +FCE9006F2073F1C64AE42908C2E7F21EF88422526423ED8E341F869B2EC8E9BA679E9028\ +102C9BFC:\ +60FC4F62E03E3C0ED6DD21259BBF3D4C24031DFF6A20ADA2E2D637CD0FDA2351:\ +6BC92664DBE433FC2580850BCF0E08DA + +741C912167AB5A5AEE918FB21480A2EAE39C0038A458A34D4AF86F6968A97A945B4EBCD8\ +D74E5C1D7388:\ +116F94F7C970083C2F918454F7C5740F3F92FF83BD5A0C5F8DE592FF115171711879C6FA\ +739E14D0AFD7:\ +DCD3F3A96FEF4C6DAD109A65D574842D04029B155BEA7AD54D25D3FF8FBE5A2C:\ +DB7728ACBA219FE1AA8259448BE3D6DB + +CAD05D525C37CA43C187403F3357EBFB580ABB2F782CFA7B9661B1F71B1809920EF0D897\ +13598CA4749763DD:\ +C17D53A4B37EF4AF33DF4E0F317BCF8541ED66DFACDA662289B261ADACCA3D4C0066159A\ +BDCB108BBF5C707E:\ +0CBD7326ADF581A058CACF74A3404D3CF9EEDFAEC8E47BB30BC1AF1D3660E0E4:\ +C4DB5DDFAEE532C12B7313A9258CE63D + +6032DDB7CAAC7CE2CCFFF53592FE2F40280F8C79E312F4DDE307E90863A9CA18E320E0EF\ +27B21216216FFA8EA570:\ +5497807495FF72FFC8C994E00CB5E7F5C521C86965FB17AD3578EE6240233A7E2C9FCEDB\ +FF7F1B05FC6DACF4A0C5:\ +567AF81216E5B25179143BC1C3AC52D940F93EB4EAAD54AE0A6F33661CBE0EB6:\ +EBF6B3BFE42C2AC5AD0B02B7D294DFBF + +F3DB2D14DDC5CC45CEF2986CE9775A64C435B36D305DB04A75FFD3BC83ADB8595397EE9E\ +1B8137A8227535B3984A7267:\ +7BCED3DCD661CE1BFF9A6D1B52D957D12E657DD6241F64528C496B6D5A729783FA011AD5\ +788BE7DFF57D892A0ECE7A92:\ +818DD281DE7C051FE22A5CD1FF0154293556D693427EF49CB72D31E05B91FDDB:\ +4A3F1F5AC035B0D18543BC763D42D61A + +83EF6209E5EC332E9CB0A2F73EEFA34EDCA0DE7148188A5A5E8AF5812EC9F272147901F3\ +8B811FB759DA8060A1F93E972204:\ +C4D6D68DF04F55151A46D291F188C71E3C59C06319D4A6B40B86312E93ADA7EE4CCF495C\ +D56E0610ADA4EE49EB4982601DA0:\ +06ADD322678535E83B950851EC12D6DCA818D19F1041F69919A1E0A16D868ECE:\ +8842C25CB6F1E93F2485204B8DF65A61 + +14D9C539288AF393FD3552DCFCFAA4EF497514E7101ECDC92E875BE2D958D296FF1BE307\ +DC5AFD29F71460DD7F093A392C8210AB:\ +792DBAD92AF1F5F5E5AB14060E6245D4175A6D73910FBDBFF76A08493464827A108141E3\ +83E3104E3F4B7EC645FEB7740A426AF5:\ +2638477FF92C0A140CA99B62CDF46452AD58B01A2DA667BD5EB3D425E9EFB5C6:\ +FC9E9308891984AD0B305CF160A64B45 + +C4E76E643B92D878A7BC2693EA1D0E1E86A06FCCFEFBD91506D2B8C6024490FC965F037C\ +EBA97C607F808E48C9D86E40AAEA079FA7B6:\ +66BBC945447CD9FC87CB47AE7F72FCA83696BE3BE6396ADD9EFAB87A3BE17718CA2E49AE\ +00758AB922A2F2049BE84577DDFA228918C7:\ +ABB8BC67A8299C34C4B97105230E203F1BF8032C876E908E6024F31F0778C2DE:\ +03C8C55A12AFBE4B5930A8D8FF80F1C9 + +C8A5C5A939F5872E56BE199D24422A7B99F797617B5E39E02729AC05ECB1990CF8D287B0\ +8A718495D9F261E9110E4EAD62AC789918CF1CEF:\ +23D2A8B6508552F2075D340707541547F37E622DF4DF55EE3E0F4E0E610216B7E4218358\ +ABFD86EF3A6A5739A0EEA49267AAAFD89B28D5A4:\ +5DBF7CE56C2C431FC9B69EB80635D0B7BF58C7860A1EBC876914BD040978391C:\ +9E2DC1FD8EC1C9E1FD0D5273F1379D46 + +37B26B33453BC31C69BD09D5778E04AA8F5FFD7F367727B30246C81BB92F9ABC3DC9EF72\ +171C3F38B76CE887F647AE42D87319D4209857EBAC0F:\ +8F85405DF5DEA595B58FCE86713593BEAECD39B4F4BD11B43024A5FFBBAFA0F4817AD6F9\ +2C111C08506056654E003CFF9A60162147ABD56BB4D4:\ +6A3CD1AC06DC7198EB08F439CFED766EF40551B1361048BD17B1A88E9447EA27:\ +23783203B030B2AC2AF81621781FB946 + +44DE8E16D60C2CCB0E804ABE95CCF7CC597B1A9D0B3FD15BA2CE321273006322B4EBC4B5\ +BB90E1456947B3B289A9F6DF266FEA780FA13A2CF50A0882:\ +03BEF28AED188F7AA6128016647546160DDDBE80BA403CC4F29D9D90A5761075B170D1E2\ +7EC6ED96E7A329ABF59F7016F4BCF39F61FD82C010B4F7A0:\ +1CA7FD4782991006FF0246581729BE4341A6556C61FEED749EE9F48DE8037874:\ +7DD54BCD7665BD84E8DBC84F367AA008 + +8136A889B8105FBAB44325DC6114F395CEEA87EB6E69D35C6020AAE00B47942B262157FA\ +273B2317CE08255AF899CFAC6A83AAB7D4C5FE5729A64AD9F8B7:\ +2D6B1B438E8F7A70555902ED6FBFE2ACFC371DE250F32C9D5B75321913837E36646DAABC\ +E5B69AA971A0C6FFB5928E0A75A13E004BF241E73754B74F3947:\ +9E8BFDA871A63F32DC05F53D1859291E6B099E2B4474A43E570D6D167A2E99A9:\ +51027A0552EBF97D8372668BDF106F46 + +80E71459F0F7DD4E490FFD23063D1F741E44939770B6128F07BBFBD48323A2CC7558A4F4\ +CA4FD9C32A137C5AFBDB278A9ADCF66B0CA5086D0C09126A7FD5D20D:\ +AD68A517A73C9485AE996D79B90344B5ECAE6C11EABC4F268B165232F7A062F73FF46E7C\ +674C706F14BA70EF9C77D5E6DF90CBE09114AD4E60417A597FD896D8:\ +9ACDD36A9AAF77D9E2C6286DC456D461508356818F4FC2CBD001A94037E42E1F:\ +0EB87233AFD4C552D9D5ED5C415F03E7 + +0EFC9979CFC65020583D4141A6422CECFC1E816B8682A1BF73D05175E8A2E83DAB239DB1\ +5DC57C4ED427EED3C73491285767EBBFA20CCF1CCBA594FC45980A34C659:\ +ADECCA8B5879B64CF35C8AED809570D12BA0C0EB19C319C0B9FB1A0A33C04F48E2B755D2\ +CDEA8C0582019F7847DBCEC023A4AD27CF4879C07CC33CAC9DCE9C47A491:\ +B0B664A621FDA57B3DF93323B61DA43CD55EFE1B1954A8B86CDEF4963E082B5A:\ +63DE5E4E1401030D736BC327D9DB2BB8 + +FD8A05EA9F872847A37F33D66906C085D10DD980435028CC0F7FA168CE8363A8A5420E33\ +67DC06AB69C2DDB49C1BC0E32E1F1316EEF18C01A95C23B3342ADA89C131E42D:\ +B0A2C09A27F4128353DA11A0797B63AB54E2CE00BA58BB765C8F6F65930E69258F2C3F30\ +914FA964AADEC9B8DAFE39C58757D65CFF6702B955550C8A494B64056B906FE0:\ +6C62EF4976E50622F623337E32D70DBCE1E423B4CFF652C2ECB1D3DD194B8722:\ +B7F60B3D94FEE7768CD92148FAFEADC2 + +A592978733D8647858659889303CAC080E95C2B2B26642520CC6B8598C146DDEFBE1E4C0\ +68F3FC0BE9CB0EF3D61000F2E688AB2D9DE7B7A28C3B32AA3F8B872F91D2CCF9C927:\ +2B3D0D935877281412DF2AD20602D0AEB7E375826BECF964E5EE29A8EA1B20529943BE59\ +5C099BD2EA0F70ED95BFF11FDD52069274E8D21B00AC5EA11369BCA9E6052F1ECE13:\ +85357F480C3AC5C8E412523D2C6D45862CBC91394DAAE40BC20C58DC7FDC113E:\ +CB11FF4AC49C513BD56A79104FE48F89 + +60C42D6EF79C6FD920FEB2A9EE00EDDF34B3339F99BF13ED42FC65247166B19C42099DA9\ +089F8131856FAC9CF0703AB9C73DADDDF700290479146F67B49770CA9B53511D94F6D7A7:\ +35409AEBFB98BC6CC70BE661EADF99C7E1133F912D8FBB957A5A61AFC01E622864C1AD2D\ +B0898B0D3682042A510D65584C7EFE9517D0CEA31D3385C857AA334478BE651DC48E81DC:\ +53286FB5B6E08E9177CA17919D845A958B7D55361DDE5E9B09B40138BE3F68FA:\ +D7FDD75B3F672908845354CDA2EC33C2 + +55204AF292A15EF0907E3A05FEF0BAB2FC199A874FA3B72B1959CCF5CE59B1A63BC7D0C5\ +709A1EE8152A11423FF3D021726C9B914283610530B80114A6AB16F1821434CA0B5B66C5\ +1181:\ +790F49950B195EFFE12FEE3DEE248147793869ADE0B46B412F702C4AFDFDC92A95889D45\ +F1828CAD935CF281BFDEFEE68057906564E63509A464206A3939C9787AF559C2F18E857F\ +9794:\ +CA1AA91974D69777335BD4CDE41584FE09A0F90B4EFC1DAB01F5F6EE475C5B26:\ +A753ADB21556F5166B8D0EEA24AF4D20 + +F1B63FFD3C223E65972E716872206B656F036AB58CDC6BECF814B4372828651A28FEB0BC\ +6F7D5E008A0C9D069C5765D9613F75AE3CA564089840C2E5326AFCBB73E9677D60261C1D\ +11DDA8D6:\ +05C44E476B45156EFD1A73CAAE0CCB4A02E7A3BF461377AC5573624F3CDBB03E5F040EE0\ +0A628EAA819B84461B8F39D63308C5FCE21B823AF0508384E0A5784B99FA47AE0A15F8A6\ +31CADD11:\ +67EEEFDABDB4E221A3F5D331E021861D80B3E52EFD3662FBE4B7F96CEC220668:\ +ED8A0E2821ED9E46D9E47973CCF4FD25 + +415E13F78C19D639C7E2A262D03D17C33648D7852706B0787C5DBCA2F7BC09FCEB3C570F\ +CF3E121AD6B9E467515998EA53B59532A5D0C86125928ADA505D07E9C0683F0F2862A0A7\ +09B76B9F3E5A:\ +96D6DA75EDA6029E162A70667227790B28DD1D08731D08024FA175861A30D321CF95FA07\ +A96077F5F9F3BD0EF809CBA394726CDFCED17507C89295954F7AF19E7CD513D18869E7B3\ +418E193DE7E8:\ +BA8A42A5079A1211FF373CADEDDFEBE4230384AE50C0CADB777689E9FCE03021:\ +F2CAE7EFFDDCCC54DB0DE734347ABA8D + +5ECB18F27BDBC1469A4EE7273423D51CF53DA0BBCB3773C04F90934DF1A4E686B76A2CA1\ +9B325F91CBC13CDE9FBE0E7FB1D205D78EB92DF19A5AD39D9E5CC07A4329EF14115D5A89\ +4F4669D6B6C3E920:\ +47D37261C8ECBB954E6980BE6EE8A89CC31E83CD8703AF97B40308FC71FD5C204C9FFF43\ +B35BC9709CF9089BE6EDA572EC4B580F74A3C25741B147D3F2D06A7C5BE8AA35DF232546\ +F93B603A91A4D4AD:\ +00B1CFC598BCD9B708AC9CC600AD951E95228C4941FEA43D3E9F9C4C4DDA9F57:\ +AAA2D1218D7E5586150602486330D79D + +ADCBCF6C2797D693DAECD8B395FF2D8951D9D58748398E1886146CF39B6BBE94AE5725B0\ +8DAE80061365508ADEA2F7E27006BC2EB8296E441D9ECF3A1F105AEB72A7B7ED65C0ADAB\ +96DDB4C56D3E6CE7EF9B:\ +204B284617F9E475636543C231788FFF1566DAA35B7188BA5502116479D8CFA3571726F2\ +3F83EE62960DE1C5512364AD31BEBD71778926B4DBA86C69C87BF62D590FF01D43A7FCCD\ +9DF526738DA3ECC07313:\ +D9E06DC86E89570392B95234B2B4DD1D424FB5D96D8E5EE6522EC023247240CE:\ +555BBC29444DF1C9B19DCC36E8F526E7 + +D1E3667AE3F908CA70E42ADB571765C2977A7597AF1E93568BF144FE6B8774AEC889EBE1\ +C55EB673F2E05C9049FD38FA112413C1F5DAD6400104493225B2A1FA2EF314267671682A\ +96A15FED5A0920BEB7915759:\ +0D8B1A4D0B4BBA07DC3D66FEA6C79EB79845A303A99D0CA6A1363494FED39D9B2028323E\ +A66F48420620AE16522CA5C036984E431645D55BB71C9729786A2942D246763AE14D4D7B\ +E8182F4412706F88D745D29A:\ +8FA2C547E80F8370524EC80BE768591403BC8B84A31E823E1EA7B58D13C2C1A2:\ +FC552663E080DE3AF70F1843B20C2321 + +9E66CD55C5F5ABE2D9F479572D1867AE07654DDFC4B09603A7268BDB98CF22A15EB207C0\ +5946957927BF3442FB92CDF2BC64CB1AAB4267884C65AB29F7C7F1AAA0C797DA1BDC2FD4\ +7E02566998933F0371F054AF75F7:\ +4998F91D12BD0CD7C9C3E4D7E4AFF383D87555C75523452F7764B8CB017DE1C9775DEA51\ +AC4A84CBC77FEA7CF4D4ADB3F79279E73EB443513AC9FBFEF3F210F80C553C758149CEAB\ +515578E988A8F49D4B87CFC7C3CB:\ +EA2BA62A693024D30A6F86F92534B011D6D8ADC81E6DF43A15F1A38B077B47C7:\ +B09F47C60D4A913E80DBEB9572CDDA2F + +0B515541E94644E05C6D33B0DEC22322A23EC8666C40697D58B0D7E28FE278DC8C6747E6\ +0924A09442A04C167D48CAB29D095BDCC0EACEED2C841FBFF1010769D8829EC1CABB235D\ +CEE28CC09C4D905CA1CC8BE624298D76:\ +0FAD0D901C43395C015B252EBF61F66FF41713C2DF9AD2245E1EC1ACBADD2007412DE768\ +E5C986AF3F26FC489676AE5F7507AF559A8A23B56C417FA1452D92CC6671F6E4BA5C1F60\ +819811F9704953BF349CA5C4D3A0631A:\ +E659BCA785C4BB8BB49DD36F132EC4984397B2665B97689FFFE7509F1A1D7551:\ +069C61C342C4DBEC240C709C3CDB361A + +D2C5A20331AFA2FC82F0A0D64160B4EC447FA5572A26EC3C64C9F736E43B0915AA7C3E1A\ +B6A9D36BE4A15CB26820E29AACFE83024959676FF05376C1AE788D276079F199936AED0F\ +0F688E42E337329BEF9336FFA36FA4005399:\ +7DB91F84F3477868CDC873EE908DDCAB90CBCAF18C0A70791A120AEC86CDB215E6221A70\ +14482F9E3802EA3467001D3601A63C92C6AEDFB4946845F13A52351CDCC6D5F922D19DD5\ +B1EC236E822F62655427E62A4D0E84914622:\ +FA7AEFC8F4B784C193C785B93E90D08F8523FF065E19B2F8CE817FB401A21FCA:\ +A66594B33C8A53C811C2D97CA6D14303 + +7255CF6B4E647EBC0AC95A5695F0AF0E9AAF91E3D95749D6A49719093B1200B9C6BE09B2\ +6554E36EB6652041744605EB051062C0B6D1CC01257709F751EB7B9667AE7E329E43EFD7\ +44D96300958FADCA3C106AF1733CBCA1AAAF823E:\ +E3D3CF5237D3A038F5F6C89EA9FCA960FFF212211D3C2CB3490607C9957B553335B18C55\ +1BA25506EB2CC3BFE9F3EA6CF0AA9EC434AA592FF77B61BC06F0B2B95AFA8FF5FA494E94\ +DB731F57DE8529ED53A50C42F986C16EF7C7A940:\ +A26E2B0A05D0283D38D7169BC2BA47226EDD259B8D57B381FFEE069F1B98046E:\ +C4E7CE77538E9914BEEFD56DCFB571B9 + +AAD33FEFE3F84DF826588A512B14CFCC1D853F2AB84203C1D4D8F8B86D6AF3F7173F6A6A\ +A73843D5658489507104DA3D7BFCF5168D986464C3448F234CA69BE3DCBB6672575564B0\ +2ED92FA0F3877DDCC06D502A33D6957A0E33F2DAFFC9:\ +CD0C9764841179AC19328315A39CD34BAC626AB5DB485D0F9B46059F54E08C5492B908DE\ +07B85E7A44EF9462BA8E0A81FD1220C558295A948DA4DAE908535719C1F88B1560673BD8\ +07F5262483B40AB9BB0C64926FDCD1061E504B4EBD76:\ +6EDD7092DA78BAC7E1AC92E3770134A03D2739FF5D34430F7F4D4D6E9764B319:\ +8AEEDB0DE46407E08707969C750E38DC + +8168FC2661FBA3600E59774138459C2961176EFC931CBD6B5C33560078EF7518635D6939\ +A98B0767639E0E93074057CCA6883F7964A1668FF9F8210E95D0368F6FAEE9FA8D7D7779\ +2AC00EA2BE1146BF56204FE906FB865AD039577C01234AE2:\ +51A47CF78D2484F3451F0C2A43EB428379D1F6893C1B8A39FE3E60F685DC87C0B840E9B9\ +6FF58B5D5FF56AF2D9E6DD1B2701C68A0E845D4D5976BD315A353D67347BC8730CA8EFF3\ +AA0DF4BD6DC8E05F7EA07EAF2C39D7D47D9D84B474E7ACE7:\ +BBF6DF7DBF4037FB25B611E6A2930DABF072F65AF0A6457CB9DC93972E9ABE7F:\ +501092F826689BCDFE80F092C26B5EF4 + +81EFF330211A83455CB238BAB684E0067FE4067B8C991BC1AC8E7633D080339190E5D94D\ +B793154FC74FB0AFDAED0804E3C1CB51D2C1E13041FB81B2157BC60C1FF633D16CB4B9BD\ +331420AA12B95CC7AF57C713C24B727846B0C7227961F2C2D36C:\ +6886E3F70FD5F90852F3CE559925D769036D93CE8D9476835D517E0FB32E9C96D0388391\ +30C1C25E1B169ABE4BABA9B82C4ED74DD45F597867C5D53A0506AD37542F25CF58F4A362\ +BA222FA1DE9038A8FE543BBB44D85B2E0E4738067BDAE5DF7060:\ +432FFA626DF2A52CB0571B6E90C61ACED99991FCE9C16BE3B63F32BE944E2E56:\ +5C8A73A4AFFAD697BA8B1BCD810D8F11 + +EE2EEF94470FA795A889D2669CB2B80D3155C8B61BA73019CCEEF203FA4EB1D9AF6C1AD3\ +B2954F7315935535333C758A4EB3247E19B07308569400B897322A4752612F0FF13FF3A5\ +361DFE0DAA88394F3642B1C6270718F28BE8C76C89ED29B6A6B0BF94:\ +BA17AF1457C42E6E6FDF4F98C8E45C0FF78D4849039ADCE1A168A6ACEEB9F419F49125BD\ +F26E443EB783108219A2841F82499FCF6870724044D9CBD95AE1F4E2A3D4A4C44C54B2D9\ +90E0DEFA120414ADC438E66B298B72EBBFDD7BF38EBDC44143E16B69:\ +A249D7A363F984C302E92C5F94F8896DF3F776225C022878944FE2C2CC5B4C19:\ +5EE7A0639A58783D7E82D1FE5AE0DE2D + +577B77E72EFE7CADFD281160BEB544AF2F28B41CFE4B92C5D770B322D40DE7590090833A\ +12EF4FDFB0EE57CE0A4A36AA71C0C39B33E78EC4CE15CA6400936E1561FC6206916DE9B0\ +3BEB08F90930048F493C05BED453ACC98FE7AB2256B5271A1E8958D07AD3:\ +A34F475248B72AD9BA2F461A690921544CAD263EC739AB3ADB4E42652A547553B3A303BE\ +29F23BD9BE7977D6750E50A2106ECF52C0A6724AED2EE8D482D09D0D2B9AFADB78B357EF\ +0F52E027243D445B5066572B0CF8812F3E19475650FE85DE610EEC640091:\ +AFCEECF27458C2A9B8F34603C639A5FF1250F1D6DEC2849F0D74BFDFAAE36660:\ +5C453B6546216E318A6036E803322401 + +4A0F51F3716D41FC3E5264557D19CA35FE3B70E215AE6DA3990D1EFE383B9DE7E50DD085\ +5F751F95BC093EA76843089F284CA6176D2F25999230F6A5B9670059736CE084CC167274\ +9504BEC04B22F26045366030599337D1DCE783ACD0BDECB76DD4E9E8D4BE9421:\ +D747558707BE24371EB6DDA6B5FF138987CDC42BFD71D75BF1D6DA35591E4B35C32F9F07\ +A1C0B82A55AD28E4DFFE43764A814CA13D60EEFBDE3345BA454D49179662ED53A9F3FFE0\ +92D8DABE481E3DB0D7E34D6296102BC45D61E1719C864FD26FCACFDBA986A6F1:\ +EAA4738DE7B609D36A756B5DCEA1CF8F4359248FD8A423BAA925F0B6BCA7DBF7:\ +7DDE259B3EC5CD93A2734626A9B99FF9 + +D8D191D620CA6DC8AE66658AC39D87B8465D32BB2637128191F0F92E47C7E99E01FD4B8A\ +8BAF767C8D66EC280C77E877EA06435A7EB72EB477CC2BB6DE52160E7B66F305DF97AC35\ +C821F418E1FC56FF8617B9B595CE824207099A8D9CFE24B616F14EBCFAC508C37127:\ +6A320C22C68E984F0308A5D626C16343D268693F283FD71885860FBEF767B02E16834BFE\ +FAA78B6A806D2E0D1B54451532B4F77365989259B8B48AC65C0B730951DE373B4D51276B\ +0D364BED18782613DB2057C4EE9AACB56CEB2D0857BAD4CEB9A190AF7B9E04B8267B:\ +EA42B4BBDAB135C2B0BC54A539D5C9A3D9B6EDF21C92763CC8F468BCA9CE5D2C:\ +013847F7E5082E4F5FD6DC16D754A80D + +A7033720AE2A602FDA4BA5127C4EE042858D0376774704D582986A848B2A0DBA6DF135CF\ +3F1E5D65F68E8940858A35E9C61E7AE2469CD7B08BE72069354A2A13955FA21FF3B4DBC2\ +712647AA20D73428D426F9B279B5A0C82E2A2620F836B28B03BDDEF45FF3366DD9AAE66E:\ +7FA21E16C5213010DB8F3DDBBDFE1E5AA16696875F632EDE3CB31B4325C4E2135B9D2C30\ +42CEB5415306D0FD7AE237F26E3F135732BDE6C753D0D844AB8270A094D5B24F6C753EE8\ +6455B2E936F2F5EC5AA4058099F6929C95AA2AA6CF70CB2C519D6854579CA23192AD83BC:\ +AB8512537C3519628BDABF83E005E8685A180AAC1988E48E39A95030BD4FA6AF:\ +693E3B87BEBD7D144FDFC1796922F843 + +E84897FACE6ABD7B897B935DB435C22299FB4346BEE1C4381948622ECF3328172D0C3A48\ +A30EA2411201A5907778C994EBE29637A290EE6DD503B6EF1D53D368811D5DD731E7E44E\ +27EBB7382E6AD4C74F49FFB62CCF996FDC7710B943334284A38957EC822B4F448B7482CC\ +B972:\ +C5B740D2E9AE85FC5CFB4ECD1E375C05AD9E5040A8FBB149320C263150A83F2DDC3FBCDB\ +DAEE0BEB6C1CE6EBD3713DCA848F87200922C1879238E49DDCA5F931F1EA2CBC586402AE\ +B83F1BF2175341D4937CAA2B97F4BB51BDDA63C1F50686F2C40AACA7F1F049F08D43C6F8\ +7E06:\ +69BE0E539EE3C48F260249A10B2DCD3A63BBFBB5AFC85D9AF388B79240674A6B:\ +9A1C7753E6140825999B5695A2CAA7BF + +54D9C7F322D68ABB78ADA56EC4B23C1478DA181F30C32732C9ED38BBDCED81F063255395\ +C52E8EF6BCA23CD23A70BDE242DB86265C11777A13CBC9752F2ED55CF9D816C2F83AF85B\ +25001D486F5812E39F4F661044091E10C3429894E92EA4F87CC998E22ACBBF867D3B5B20\ +C97857C9:\ +1C4D79F2EABBF97E147FB8369933B4C7E7BA77C6A539F571AC2AA8E37C5D8BBAA1308DFB\ +BEB2F892BAE9064692A20B8A2CE2A1DD8879160C7E46E2E5039D5C32E50BDC961F3A7DBD\ +A36AD5043A87C9F0583EEAF9995994E764E19B62CA4410A87F33DEE40747EC23CE6E41F2\ +80858149:\ +B66821FAD6EA6320F3B5025EF909411DC68120198DB4B2A7BC148EA922F64DCC:\ +3A875E75096B58800EE21B31E39BF38B + +0EDFD9C739C9F72766EF8962032C1003669F5A648B0D21943E99DC5BF7A2507985223324\ +2187574B279FCFB57182F8F9832AA9E44D15ED2D8386AE4572986FBBE0E6E0D5D3AA4DEE\ +E2188614F7A8A381B335FCF9B899B86685320D457D85C9F761EAF43F49B9C9061AA606EC\ +A4750FE198D2:\ +87CB631FA8E039C050740F72698E74A93D758BF0D090B1993D6F7042E4E3A6360D0BDFE4\ +5EA8423B1C0FB9ECB9514769890BF994BE04E7A17874866FE1A15CB9C785B0A103F39384\ +A54AC746673A7A98D9F9E20D409F7E172592CE58EAAD74ECB2BB56C95C6CFAA6309887D8\ +956087009252:\ +33B871FD2A012F18E3914F1702AF7485BB793B7DA154804EAA715136B568BD6E:\ +596028337CAFA821457B88131F5E644A + +00FB363E56B460D690672DDFC0B71DF6E19F5A5E74E6E85E936937A054E8F7D87511FBEE\ +4A982792196FE8456A849AA1C2E8310E66D6C4BFFE084E791A5EDBFFCE270A4A50E5E238\ +2A18C3B9DDB1B71EF1E51B3568B75F423263E025D4E36012BD4350C226DC9805681D6F74\ +52591921AF631F6B:\ +33B7C9F0C16B82C6D6B08A42E1467592FC9F4D51DF70BFE52139614AAB3FDA3FDC97FA0A\ +235A2AF801134B58CD643E325A020AE796E333C9B3C3DF1208AA7CA5185B3FB1A7FC3B79\ +E717FE1A8B4AF71C96C2A58576CF14906E0CD7A8C4FADCDCF28145D26131DBD656ABF6BA\ +7D522FF9FF23AF29:\ +51D9223DE781C2931F7E2C08CBFE7FCE5CC2AEAE58D22819A60BD9D4A688C5DF:\ +0A55917388EC7A7648973240F8C2EEA4 + +85F25B5F5D3E68479A0F84CB9F1D92DFFE17975C864C8A974AE1E2DE60292D281712952C\ +AF99C570CED2854B6C98BDF025DED8D8A873AEC8276AA9A1A6711C49FA842C4B446EA596\ +3994F33C74F7C9074B4576750770BD5E5BD9CFA01EC26440A122A6BA0E9A5E4B490581FA\ +BEDC940EAC9D6BE86524:\ +E4BDC3821AB65D06994979873EAEB03796A2A8F5B4507411F6E96EE5A246118EBCE8BD66\ +9514E234A991D708FF1704CB811ADDE53BAE3A147EDF0CAD867ED1547F4C4CF7199B35B8\ +C548D037E494E9DB52ADCDA17129563FB928D13F8EB153A4BA85F330F263FED7B14E66B0\ +C37CDA03133158D1A0FA:\ +FA54E69192980C674DC51DF702B94A43311661E98AAC776DD7F09FEEFF530B6F:\ +DEE6D2C5DB36158D964F28370B147CB5 + +54E53C0739F2BA49B5A2080E324089051EBC24783771981AA4EBD0E63ACC86BDADCC32AE\ +88099729B4A72D8969D2EB1540F8A7FB3B79C5A0A7F769054EF2EFDDCE4BCA0294AD2B02\ +ECA48840A2A0AB20437D9085E905AA2074FC8C3561C564F1E992FBFB15877B7CB54DCDD2\ +7BECDDF9AB3A58699D4B901F:\ +6D4B53FC1B7FC8B97BA8E1D1526944490B415D3D59887437A24F8384CE850F8005512A8A\ +4BF1E79D03AC1245600DCC83EA21195835582B041B5AB2588DA8BD956D2FB69465485452\ +85C2DF36D26CD09B082F1CDB278F86FFB6FEF9DCC3C71E9CE6B629D7B2897B69CFFC2E14\ +510B4DEE8B9D957FC5AFA769:\ +D22A6E996F80C4AD83209F4E47A17D78EC0F1343CDA8890404FCA4103D038056:\ +3E4EDE2C0488BB09BC4ADFB3D1122E99 + +2A365C1E10368C49339B3F64A7F25D6682E34A3BB273DEE16D6679B7DEA80FEFCE351964\ +587CB68A939B36D705A32F1760995CB3B9276BCB06AFF5F68CCAD25ABB7CC702D6DFEF85\ +722303C4D27BD81B2D42D2C6A47A9BC4706CEE256B5CF3110705753929B95248761234DB\ +E773C05E79EC9FF958DFB728F8B5:\ +75BD73BB09EE09FF5B8E138D84D776BB8D9B26274D42B012B1D252C22A0E29C66B2C6988\ +0EEDEB0F02376EFDE6F02C85ACDC24BF7AAB725D1CE86688ACB31C5C91DFFB290968B415\ +F7342AC9D60A49F7CFFD35D350D4B63DE597127C5614D609CA27EDD1CCD869D3C4554C30\ +81450A67A2495BAE987239937DED:\ +7B7E24D8792EAECBD7CDD6A43A1D0DB9681C8964D1A55332103C3ED167B2CAD7:\ +8EB77D48DE2CB3E862CBCD9D53234A46 + +BB6817631F1F0A703F4D5896FF5C3CD94187A82F8287347B80924856B84CAAA3A05B892C\ +C8D8CAFA85F65DD1922F017728CE2E0ED7D4FC9CE844AC9FEFC79FE1EE7181939F4B7A91\ +213880D6B725FCB8348A4879641A628B7BEAB77673E4CAE70CDF36CC92D3784EF7D529E9\ +404C1E54A9086D0C33A50661295ABB24:\ +A2875C6E81960A33F8EC626B9E649747E956690DC4DE11801AE67EFD2B563695CC8C999C\ +1784FBEF30B753AF38C413E361D523C42521A4DA656BA0A1076E8773A335C854037DA8F6\ +E84EB48AAFBEDEF12D4451E9FF1636DBE938960753D3E0FE96165474298512792B8C457F\ +83A8664A4D679D06C22FAE43465F9549:\ +93C474796CFDA89D8FAC562ABFD5426E1611582D0FE40511A503119A48A07202:\ +81DB28BB02B082FE9F40675F752B9F7C + +AE29C830ED344F0072FCBDFEC9B9C634703819B24397D59C3D5418B47DD3861B5CCD2119\ +66B4DCB3FFC5E97F6B171F5C51D75B18AC13A78E2CDDEC9D4B23ED26CBCEAAE29FF78F01\ +C5B4201FCEBF7BC029C7730F7603EB456D2AFBD27581BD15941F85E816AA6EFB0D7408D8\ +5F83AF88AF157D3C90BC849031CB9B410819:\ +835993AD13882518F2A1662CA9B4160BEDC60E53083E1F8D72CA3AE2F890856E4B52832D\ +A83B341D9D992C0D9E489BB04C75149624C6D645BB9909E12711FC087C56E1210BEBA66B\ +DBCFC865520E4DEFAD4000CE0EC528916A415C4661E1ED7095E5777BF375DC31CED5F966\ +4C79CB3FB80C5EECC2067B4313CA27AF4F8E:\ +11C63D070095FCD408DC7E7596C177C0A09961B2BDCB6E7C0F300C918E7E830B:\ +41EF5DF5CF14D6D2C14CC4CBC4EADAB7 + +BFDA49CDF67A114D29A7949CEE9BBDE5D26FF8E35407A266E12F98FE1247D74A1005366F\ +526F7460FF5B5C45D6791069BDF075C8BD396BA71AED8B7F812F0A31403046F30418A11D\ +B134127434B14CAF1E696DE716B41AFAC8FAC96687ABB8A81E1EB37C0C518806673A7395\ +AFED27408AF1B83B3EDB1D1AAF54B3C754E8361F:\ +D645EE5B89B1FDDE1056BFE827B8F7C2DBEB72E89E8ABA4AD0915193916EA8E6AD540288\ +69D0B1E71E396881006482C013B25915563C492B55F6CFF5DEA950590228899EDCA68C81\ +9B9AC2A485CF40023CBD4465170232F429D06DBB42E4E2C9B5E201EC41E4DF5C9674A1D3\ +2DD33A341E2E0D13351CAA4267BD869BB5AF2804:\ +BF4DBB8609E7AB12773DEB38FA1FB31DEF23A89137E4B292EB569028B6A5F836:\ +FE53D28C28A8CD12C0D66B79CE6EE6C1 + +967DC68154B9B3957216DA8538588B899005DA3D2CB9500B1AB2FC4EE815232C01970F19\ +BF4068081EC07B041A6AC7A2FD97ABBB447C7AF73C0286EDCD99DBB6FDA189BA76212EC3\ +7B23A72FA8213D5C54AE716845E00262266400DC041D89AA69F1DE8B600F66B16485FFDB\ +5BFF89EA33625DADFB00DC35827C4CE73EB098B3A6639B26:\ +DAAC288ADD605085CBBC9867F0FBDD007472B15F34F8A7A91F16208CE15F0BD2DEF3FEF4\ +32DF84F66B1463777D3B2F0E3D2A41982BD845217383412BDDF2EB628EC8DF59240A32F9\ +FE442E334CA6670C6F3AFE7835C5D12E064F272C610F1084CE39380E029D050E5DC5676E\ +D7DD090FEF19A547EF90258670B3A49349728733E69CEC34:\ +B6E12C2EE1A50C4860591BC5AD7677BE5C77120BE31814A03B1B308198853950:\ +2E78B846599FB10E51D8AB906D7AC754 + +6A3C46C05E280864DA7660DD5600F4050AF7EDE52B786F246C2BCAD03C8A88B6BBEDAC3D\ +5FE79AD40697BD88EEE4CEB3F0C8DF2F0F5381321D8C6E89049728B0A0DA9A71AF00DF1B\ +9BA71565C73F042CE22FFAD7B9DE33084BEE400C11E6A6F8398AC35E816E63B42AC23098\ +E7C5CA9B4D78395019B6123EA198EFB6A2E92793BBE243B46B1DC872:\ +2178CB3861AC4ECCA38D4C31EF1EAB6575AE0012BB4AEE9615069F62013B920F13797DB8\ +E432A8DC486F62A9F219FEFA356B8AEE7B1BFCAECE0DFA4F94E22A2219F6468C2D15A69D\ +11CF93B67AFBBB98F185807D32B794C6FA8F22794EE880084F6BCCD8CB5A7D0C59D0B737\ +781A60B29F17290D39422BE10A6AE430AD37C717D5C461EABDF8862C:\ +91E98D4A6EE9D7FD83D643C3BA829746FF2EFF77FCBFA41D44CE95C4CD76CAF6:\ +7B659AC1248FECCA3EE765ABB8D93D1F + +B0B0645AFA0E15A28D3EB6ABCAF31C6996CEE3C93B76F957424FA82B174BB3E9945F3969\ +094C0E6E5544D64606B54575CB6CD6E40964B84E94DE2193E7B9A00D4C5D140976DEDEE0\ +40585741F7ABB55CF8EE815F7848C4CD48D30C16783E76ECC14D384F480CE896532CF6F3\ +67E23633642794E6A913B871BDD702934E8968EBE1B2859CC62C01BE12091CFB:\ +406EB5C237784660784E9A1F477E4B8655B07FC54D1C69515C1B046005C05B82D8065886\ +39EB44323FCAA1F797D210FC51C91E3A51AE8236C0C2D6C521F2FAB29E89361BDA2275C5\ +43B54110AF60C7829D6C5CBC42BAEE86FDB0FF22C08EE59E81E63F0A98A6781926770B5A\ +C7792CCEA9847055813F065225B49F387E474A333D8B50926E3D7864035D75C6:\ +DBD7D9C318FECB268FF109238110F96FCBF2400BE054071478C7A2AFF75B384E:\ +BCDEBB1E6BC37F18D49C0A4A1C7665A5 + +C47325105EFC7B78FF868A0E1CABEBB41B6A184780A52AA1D1E78A284C073089762B8029\ +9A628B3B22124250CC683CDB54DCE31E4072708C232129D437B89C0CB8BEC7A8F658291F\ +50AE9C66A0D62E26528032FBECD9B3112CCD022B7648BF995ABC46C57E821B3F3CE0EDA9\ +7358F31024F532C5D560D016CFD316A04FDD29588E6D50E681068EFDFB8361F93AA979F5:\ +D1043171968DF2B850257D7D14FBB7DE4E34FE62217E9972BDE0283E6EB2054874C6CB8F\ +B66A18A6F6885522D719EA965A0BE5F079370EB76587B8BBF5672FFD6B4390956C5B81E4\ +0AB21A15C8EF17D1189B6EF8E931A07B192ADDB3CEF0C66B28CF545774762CEC9968EC1C\ +06FCBA860BAEC78EE635495137D4E7B659100C59BD4496A850BC0FCF464531181F47EDAA:\ +B58E1583AFD26D09ECC1B81270BDA381ADCE90DA1A6096D27A61C8DAEDDD9F4E:\ +7BBB7496BA015237C080354FD061CBDA + +73DBE3EF41EA394F52138D24103977D8010166084F8FECFEA4C5327765735D5002FC7808\ +955D2DA9E786AC33F41A41E47D06E18B84344B4A5ADA2F925E536799ABE3367E0CB181EA\ +720EF44D286DF2223A34030E66FE161404724DB33DDB026FD5C88072D47AAE1BA89738DB\ +BE681D79E330856E4DDFCBD2E998E5065BBE6B3AB93DFFCC0EE04BBBB13E47080C511F74\ +61ECB802:\ +BCAA1E8F81FF49528EA23C4A62C40953CD98F16F91AE3EB6878C7DB5C3A6CAC4F8551A34\ +A5A624CC587A5A22E81CF9405E38913B77344DA59A53FA0BACFA1A4BBF64D234D1963AE5\ +E89159A24EB1237B93F25D652ECBB9EFD26E2881368287357D6783A8F3C1ACAB50FE60BE\ +7ABF7225F8AA0A06F54A63577634B9E930618A1CC8892D290ACD04F7933CF654A8A60AB9\ +00D8E0A1:\ +3A945A5C8FD52A46037A426C32946D59AA9B081C4993C634D9EAC2B7E144C040:\ +4C6D4D342E2582177F3641F777D337FC + +451FC9DCFBC3C8F106FC9C17A81D1C562E45341B4F05B5319C912CEBBE01743AE34D0693\ +0A5AAB36166780F9E75C154FBB1110375B271C297FC46D4B97BC70C1E8B378CB1E29F61B\ +5B0BCFBC8238E6D460054FEFB4A649430AAFDB7F01CF78A5406A3087E9C39FC2D60C4CAB\ +6CEE3DF6A3A8D2F0CD4134209C323D9CACF15308524519C40A81AFEC9736FF858D78927A\ +F66EFC5FCE806ECE:\ +C111527D486F8581AAB32257A7577B062AE1D781CF5B44333D12C3208BAF3C8E1276ACAB\ +0F4C325BC0D3FBF3913B13D2F06E8E64E2CF8017634AC9162EF32324A3465156613AFC57\ +779B9340CCCCBDEFC6476D2A4673DF123E435C6A98FBB8E59221C7667CB831EF2E7B5D49\ +26C9A022204F0B3564C66A9C8A7F494EBB337D148A8681982F70524C467D868BAABC86FD\ +50D5A2BC4C858342:\ +94EB2F6DAFC83A9FEEDF7081D40104F661916D4D68611AE3620A7E52D7C8F79A:\ +FCB50453BF443A452F735A2A7BFBC5D8 + +5C1DB0ADA94F46127F18B21406B6FA32EFD090B0FDEB549474CFC19EBF68D4BFCB3137F5\ +47C48174E79DC87CBF308E0E9306E68B5FA1F9F67E005A2E033DF9034BE4F1E8C53C5D47\ +73846E8EA3782C70E8B1026965C40CDC7D5884F763BE3E2B64AA7458F48B6BC76818B52A\ +FB743300BED3971A416C587BDDC713A8C5782E91AD001E8D3DDD0EBDB978427173AFA9AC\ +A2180F7DEE47FA5A76F7989A:\ +C8E1CCDE12CBE92D8E61F23DAEBC35123564A94BAF6F2511B4BAF697D04EAE69C9B1C8D7\ +8E6383F9EB053C6B09F9A2A91EC0EC1CEE7801B3B01AF1E9BA4A481A4C7B73B0DC086285\ +C43CE33919DA440C1EF892D9A254FEB9179BAA1183EF319702EDB67FA2EE08F43A719D5A\ +EE5D3D7E10F0599278C70F25104885DA2F3CE797D3064FE6400366950661B6F703C8FB9E\ +1F773D893DCAC13DA94162CB:\ +E667049150AA0CC53BAB66F3EDFD5C32FBCBA264A6EB12D4563EB5E1E73F2D86:\ +EB8D65B2A91A7003E9CB84241B1DC009 + +734BDE1B88BF91B571B7EF20524347DEA07BDFAEA8D194E00367A905DAB483F76F923087\ +B1E307EC990148E1C3B2E9DCDEF1694D9CEAE1A86A2D092D84B1247B5DD627B68E6CBEA1\ +7A539A5C650E8A6713ADDC2517B8FEEC7656264C795B1B0034B30B302DFBBEAAA12AA6C4\ +2BB3857A3C641A7A760C275F9C01521432A697984E12C2C7727A538834E90750D4FDF44D\ +F7083842090196A95D2E8143AAFF1D5E:\ +8289B871A4AE2E14F7398E510C5B522883893F59C8ABE42567FB879334A761E5332100EF\ +A7C6F6D4CEB8B6778D0C4B543BEA8B3EA58D198DC3FF02A8FB5CF063CB40E607087B5F08\ +DF86C906F14336ACB78832F20303533F8A7AE39A95C0AEBFA2985F97DB96E84EBB996F76\ +491D186ADC6D0C681F33F0FD3B42632E87E10DCEA36F222E4E7E8B4F2A5CF58D341BDA67\ +9516C829370C251824000BF463A75322:\ +F26DE261DCFE004B4F0B322D1CB4752F2D38279600B0A9421E1577C863A7978C:\ +2A4169C8E13B81AD96DC1CEC8723152A + +CCF6EDC92B1D17CC548C9973270FA54865DBEE4DD450683C7D542293BB2C59D2163027C2\ +29055943F7872D8CC2C9889B12E9B409D9EC55C346FE69998F013256A250FD23EC8C23E3\ +6B5412101FB35E7A0C78124BF23AD040327C608849E720EF644A552E35A2E98CB8ECC28F\ +FA8521BC4CD947E4BD24E4A70AE1A29572C746CDB98DE74477FF79101C9E75F45B55D6BC\ +2BD0FBC9CE24B569DBDC2DAB7FA88A07CF9BE2A0:\ +80FCDC8D13CDA4FD4653BE225654BD597279CE58C66A3CF67B95A8348DC976944477ADC2\ +0E9CD0E24C7913C928B2E0C531D43DD7F708FD4247D87954A7AFABE300085D169D280FCF\ +E16E580A0FF5AB435A7B64FAFE9928A11BDA14FD827D3B6DA14373879B4FF12F151BBEA4\ +17DB039CB8226AC91C8567B38DAE42015456FCBECE1C1CA8F0D2CAC3ED75F3D6F01D8F32\ +2F2822D2D4B0929D2831D9C0A801D49F77EEDA99:\ +32EA9D65FF14E80EB4AF36A9C6E8F663CB37CB6BFD131F14B49AB528614A613F:\ +3F1BFB148CB229C2E07719F6F99AAE22 + +428D69DB8D1BADDB36EA5950FB2F99124A78BCBB0A7A9B1398F84A7E121637B48D12BBF8\ +5F045718C3F0409633E263F62F4992F4C6D497AD7093BC8BB1BE5663B40789DA824AC2EC\ +929C5FBB5107969688A9DB02BACFDB400ED395091A98DA4F806CBD7A9229AB96FB12BF50\ +2243D810B6A9B905C48B7612F94AA37E671F543FAD6BCD9C6B181506F447E90F88F050B2\ +C7B7199B88AE55AB922FB1BF4A5EAD00F71E83EEA2FC4F25:\ +5050237A09192DB1FABDE4EC7E865E3969AECB8900CAFD72B223A8E08A34AF993B1F3018\ +32DB0620BFC6757BEE80D215DA0D6B23666371158876E0422D540B2DF889C9F8EA92D181\ +A79AA8BDE50ED123C0301527C0987C4EC1FC105E6B8C0EC12750AC13FEE9CFF30E5A6DFE\ +47A6E63992A803F94D6E79F5693292C4D12D963BAAF42727FB9F6B144F6AFBD819C54D37\ +B3558EDEB4A049C7947E83E68C6ACE0203C882D9A038727D:\ +4A1EA133F919B366E3084F80E89E091C87F5F703FC9185F5C8E34E14973DCB2C:\ +CC96182632AD38AF5273863621B25E55 + +C6092B37D8B6C14650D8AB31815C321B7923E9CAB069598003744F33EBEF1A693CC3E03E\ +B801BEE76182BBCE6CCAAFAA061250F5FC6BE6E07A3C39ED3F4344982E2DEC0A5075E5D2\ +A3218AD1C27F12C55D9BBC1B43BFBB79BAB35F74E1899517A839A54AD5274B8718F2AC2E\ +8F89A6CE94972A0AE020BE5256F8B5365B8AEBFEB63B886BAC9D263107A13B95E29A521D\ +3FBC7CCCD620E134D2D45082328AF1BAC6EB8B917B3F70A47B9D5CE5:\ +3F8FCC0A28C43035C055519FDBB13E8E5A4B35DDC04B62BD2AC7064BF7E4F7CA6C5194B4\ +0344F4C0D0C40AC3696C47A6CC2F800139EED2677E580BFF68399D8AA68DF7A28B95FA79\ +A1CD776739C1E2FB9C302EFB924013ED0FB2B06EB6B031FEC8AF7BB47E212859E1D13EA0\ +96E029EC051784317F63F5DFC2EB9C7E8E249BD88684537CC36785C54D8DA6F512450831\ +559BE2E67B024171A52F0481102C211DE9138120669D1C2A1F8BFB10:\ +C383B62616C48E3FCC6BB32DE3AFE5DC184E83ECB739AAEB94D82E942F0CFFCE:\ +52C109E1FAD94E490BD93584126E30A5 + +0D85590B10C077184BA269C135DD1558CAD1A3D792BEDFEF45BCCE14E9099CC4B64D9864\ +97223B4D3CC9193E37E31FDE74E31023C9D265ED49E8D7B1032F1FA13F50E486F68FBFA3\ +B449F671878BCACA4009CF4607556E85878A2769472D481D30CE43787E1065BAC0506045\ +A26456644E7D5149C54C5C8387F5E23DBCC762E4369D4E7E24C4EB7AA5F3FAC3D76EEA37\ +DB6DE27601FBD37EB44D4C3F30E5688B549A029C22EE2282E408F9EBB259A86F:\ +B317F91E9BABF4361F26F96D001E3D63F3A82F2C8DADC4E4080611711CB4A7D77FC58D71\ +9B6ED93D118C7ED676A5B65CD259B9E1AA77AC2813B62FB869C42DBB0A710D1C986C0F97\ +8517DB2EA942D0F76C06AAD414ADE04BBC908DC428A18729B4D55CA600874EAF530B38FD\ +4318F1B2D97513BD3FF17949BAF9FFF3BB84C3F0065A521B4595E9801B5233DB2023D17F\ +5204D87AE7ABE1ED73F091A63CEB338FE9BDB2B82463E6B6B05883FFBC0AABCE:\ +357D3ED5C533FBDB195DD88811F3D6D50EC133A5E0A36DD256BC0E561ED28CF4:\ +38670C0DFF42CB73FDC3295694CFA934 + +F8891DD530B83DD5EE3EF9050C7AA6A9C8A6EAAA4C8669FE126EC1C78A6F6583E57BEA88\ +84A368302C2D9C00D6F2D8DBBB98DC35152E43B1A9D744BF0FE1455A36B6164F09F55D4B\ +12290418E14A88F3F80A5EF558FF4EE01CA1ACE680FA028E81C12BF8A18A18792AE98513\ +636AB075C12320038C5BD733DCC8305551514D45E098E8E07EF0A293A489DA24BAB16973\ +D270E5D92AF34E6ADF9EBF945648192640BEE963281303D6DE6097E48D0AC4868E87A58D:\ +A54CF0CC7FF8A5B041A15C78F26EE7542BAC19254BD4D421E9A1843C66E9D8B136A80E28\ +31E6C52278CA54C79750CE64F6DAC5078BE3CAB44AE9F4D9019CBB310900282A6BD48313\ +7870CF8B0CDD002C61BBE679C2A87C7B1B1F1632DC57CC277FA4767D77BC2F0273879153\ +69012D0124BA8B2B85D8454499843C5F2FD9DBD584F9E2588BFDBA062C9F0761609BCE8E\ +0CF2B487F0F2C78A1C0B6D5C37D483F6B6EC52B7451B057C2D5FF2CD5F2BA443AFBA9215:\ +C2B6E94866DE53E7B7BF5827D5C0179A530094FE6AC5F44C9B3330D6C855E918:\ +A4EEEA6808FD5626B56AEB9206F86EF0 + +1712A86BFE8C268C84902ED230BACA2B7B1610B5E6837ECB817D5D945E009BF627039587\ +D42EFB7C3966B9E84FA3A8A5363E1077F287150387C3A9AF1719D91CD175A97156049340\ +13A8A39A90EF97974A419796DB11DF04F3AC7AD348F37969FCB4F560B02108674026C17D\ +59D191A92DA7C7E32292D3DBCCB6D3B29C09F794851BBABDF7F455A9F050A069578B6A30\ +315BFA63448CF7A6AE2EC87C507E0A762A18ADD0BE18DF7BBD4F622B1BDCB693B53AB440\ +6E88AA7E:\ +3C43430F459A8E942D7360E97A89B2AD6454DAC2E72F64A1B06233810334C549D63D0BE1\ +C90A419203632CFB5C52E205756B751630DD08008BFFD348CD67C96774AF48C50AF4057B\ +4A3CCEB8DCC2223481AFC79FE717CEA8EFA2759C4B64339B2987175D14B4C195CB8E1363\ +D4F4249BB6F8A769454237FCCA5F848BFC05158F1D27BF39E1777A3A1648B555A72DA4CF\ +5B297DE904DCD84E36EE569B3F0E1F943873576F97D65B8669ADCA2BDB322E4A864DA4A9\ +E09BFE3C:\ +CD9057AF000AAF8EEF7F304A770DA1394F8707E59917A82671449D336167E456:\ +4DF89B713AC1141D62E2C824896B80CF + +EC9A99CC500450A9EDC1E707A9480144E242DF106E840B9E8D3DEA995A0C9F63FCC02117\ +02E8807EC1ABA88F5E33645B754B2E28EDA71F1B88E25B4B03B0909BD075F3855B4F6E18\ +AB07406AD94E9C32730C09CEF69F7A4FEB3F09C83D46338926ED795ED4EFBD2917E47873\ +FB6F516F6E4AEDA8D0310A914DAA25A08CE4528D67C3E1DECA8754552619027FA6FE7CD7\ +A1D9638EDB529445113C09FCA8BD4AA540EABB931B6BE201BA372D213162E14141E3AD51\ +AF9E684896D3566C:\ +A7A266F5E6CADE688097C04788CFD45BD87FC636201D0F484927B42FADEE8F789EF93F31\ +19D0DDE8E3716C3176360B928D3006A9F42BDC12D0591817DBD82D75FBA44C784FDF2D86\ +5E11215AF461C7DD1F9E3B82A146942CEFC56DFA4F8F80C4F0CAEFDD323607F43B33FBDA\ +7B6BEDF9DDB2A8C908E6D172900D2B4CC633C610812B62CDF225CBA62E09A8A1A1D7CBDE\ +1BF1C14CBF4C24080678677AE59166314703A11607C983C5AB3C7F755B220F10DB049983\ +C1EC0ACCB1368305:\ +B86E45AB9929C8382C8B068D619CD8450FAC18D39F31D38310BE8DFB8BABC18D:\ +3B10255473C571368D678D36964404C6 + +02AD0113F276A03AE7A6C336B4DF4092F27AECFE4FE0DE526F6C548BBCA129FA24AAE385\ +0D0889FBB6F99324F7C01C749E5C7EA3F550594B98F4488F546C509CC256926174875DCB\ +99470F2D79EE7532E36A88BEAA0AB336197954B13171897727242BFE37DD15EE0F9BDEB5\ +E512A202AC3BC467C91191E83FAC86A80EEAFE0A8585E293558F7071C375A91824844347\ +5B57044ACA87243CDF11AA0838D9509A712626461E9DAFD0058A16DC7C4E8D69F53C165C\ +3CFD4AFAEC80E4F764DB4BE9:\ +7F3B26E6C98FACA940DE8DD01BF79AC15EBA4223AD8FF243909C321226B7497CCE5169E5\ +3A3A342FB1854C1802A38F87F393224EA8F518F633B04BB8EFB4ADDCD47CD2599249A40D\ +85A91CAC62ECE87834C028DD2F4FA50FAC1E6B591AEA8A454FE3BF3B41EF7C7FF533AD2A\ +5D4D690F899F5CCF8D4DF6D4FFF94E7F7567070B0309A905DC671515AA617018F7C37C13\ +763A445D48A5A4569D77815C1349A7E0BCB01D667EC0613A1EB0F12044DC748BFD1FFBF4\ +B173FE804CD0C91744302030:\ +CC207471BE9C6952378E60D263D69618DED46A78A21D8B7CA94E6BCBC4E3DEF1:\ +44F3D7AE3D2BA40BFBAA37A0709BEACB + +459C134A5BE569AFEBB4C7109D43FA4A5691B113D13CCBF47C06E90787A23C3F9C296B94\ +D47E2606B655C60C26E9DE647F4CC5BA5A49F5BCF458F40938E06BD259C20254F46F6932\ +C63C29EF311B63BE600E5BB7179FEA67EE10F7DA52C1A30E9EF1944D6321C3CE169123E2\ +E7D4B4074254D7C4998ED6C153BE0F79895CBE9B3462122BEA0FAE7B3FCCA09E5F980CB4\ +39A2F748D0E704C0184B56332921E85AAD4214EC7DA6EA8C6E852F7E1773A9602DF512C3\ +4895861E1C61D8EA0408F103E88702AD:\ +95042E5A21E494CF178601CE390B4F9AB388C698AB66ED4F2E7578A10984E30F63BED24E\ +BC839EA91BF852AB63AB170D8EAAF93FF2188D416DAFCF8C30B29455F70022284A6F934E\ +417F582B774B034ACC257C38C173556CC2909F5AF94C0E7E7CA69286CD7FC2C729DF2F6C\ +2543F4B12506DAA449CA990BFBAF39D386F36D490DE0932DFACA60644D7852007EA5532B\ +6EC98789F49E77239C236284FC94B77488FCB5EE37F0A3CF575541EE2F8FC0F2BFB67044\ +7A7E54C63AF122536C4B61B7A9C143F5:\ +DF3DE7C6FB886CE9DC51AEAC38374C29AC993630BEF81F21F725DFD4D6B799E2:\ +825A5B8F13472C46443D47145A1C136F + +158C45549636EE574B32800377F970320B9F861641425ED07021C9C4E44B5F1664046328\ +CCC1064397FCDB67015873B5EB433F52DF4936AB289A8CA161EC6A43E7459DC36332479C\ +704D956E18C86E11A8C1AABADD88E1EAA313A3D133004A34ADCF5E0F2301C3E0317834A6\ +A08CFEFD219DFB5F825CFA794DBA5971E6360DF22E3E0C15881021377DFD3EE69E53841E\ +F08B3F95D9D04CAA005ED15870B94557BB73CCE60B73495655C9C164098E2AFA19FA7420\ +6685D8103BFD9476808E38F8401FC582496A8EE5:\ +DF6250DDF592B446ED6D976462EEE2CB2D7830E67AB9567BC275CBA74CCCBBCF008441B7\ +B1593756DDAFAB05B1B728557F6D027A2A5EF2ABB072F456761AEECAA143795D93D6EC56\ +7D17F259013858513D20CB461BB51C3CD3D4204CBA768A5A3CD4B5D19563FADB62C4054C\ +9F7D8BCAF30F450F14AF29429E3E27C130FBC7B53840A00BACA0281A90293C6D60376B4C\ +6C455C771D1008A542E19B13AE1D4D14E3B8C69FB44550F74384C02861AF985BC210CF9C\ +4625012CEDA24B08842986E2DA30F9009113F0A8:\ +2DBCBA50DDC8EF3BFF1511BF0172A073CE37F42C83BA223D7573A82B13CFB813:\ +68A59DA89E8D3AEC1D4434F7A2EDD2AD + +F3087E4CCF4C82AA5B3CACFBFE367B2F501D1992D6455F10EA6C047A26ED06BF4393D53E\ +B0FD5B8B587B19ABE106269A74297B517D57D89D7CD26009B5DA7BD1B5CD40CB5B4DDA96\ +E495A02BF58108337A4F74E2A33C8EE14E730740F023560B70582EF4D1CE87C3AE5F5FE1\ +546F5C16683A0630342C319E2A5C43BBE7EE522BE44F955B4912A765B1AC476828C0C5E9\ +8948ABFC096ABCFC4FF2DD5077926C9A3F21F85D6B3EA941560A307BFB4714A11525C60E\ +4D70DCCA56ACF6FD3B95560CB6C3DE1342D8FF18828783C5:\ +996FC92E3A276EDF16CA8850CF8C9530364D170EFA51D1C5DFC2843A968E3CD1EFC50402\ +7C2E056AEB2E7AA5DC3EBED6CD25728812CEB545ED9FA552B1D0B1FCEFC4CDA5BC2646BC\ +5FAAA4C20B821A417980572112F737A7DDC93C39B533E9808D86A495547078087A678570\ +1D27D4632EA57D398F217BC191A30807999BDC509AC74AF3DEF4B1105FB8B904DD9F2CB4\ +158ED207614A07FC8F3803DC5BF81CAF15B709B099AC4F1F0968B7577A81819858D20967\ +77346AFC426792B9581202DDB4F1EB17EFFD81CDA476AF26:\ +B09FB55A95EDF75A610A03183D05A8D03D6CD9CCA7276530A72F6948CC074848:\ +0866EC523C35B5D03269F4F2FB004AE9 + +710647FB3C699E7E83D1601D49513706C54CADC3034E47F8C20E1523225BED6FAF93308A\ +653921AB1043732F142196A32329AB98094C580657617967787D738A4EEF541ADCAADE48\ +84113C020026F6AF952FAEB1F9745B6D450FC86A04A9C4D81F4AB15089DC0BF7B1548D4F\ +850CFD97C6732FEE47B2320A31BEFDA8398C4AB0D7FC123C43F642CE07AB8DFE87B114B2\ +28455479AF224BF82B04BC3341D257F4EC166D9CBDB1793946FC2BC08B72F7099128CB41\ +0140DF4FA38A2EA4A2569DDE2E3AFB3164DD2F9D830A831A323A09D1:\ +EE6EFF319198C6C10DDF6F10546A5F38490A9D9858E021F5DFDFAA8ACBBEF0A446358928\ +5E8F1EFA697D08ED42F9160C4E6EEAE1F15D78207FB207565B9DE9DFFCDD96E88766B2BD\ +A996CBD439E45578596D91E88F7706A94C9428CBCC3108E1F61CBAEB184C30E5BA0370E5\ +DEB1A9B8A42191BAA3D722CEB9DF9ADB69764820FA95BE1B48493BDA88030469CFD41F5F\ +13731A983FDC9B2CFE562881BC479253A126D57A8BD02BCEF2FC6DD8BF1AB265C924EA40\ +F5CF75F4E36EE10133923E2427E19BADB34F221CDF4673D871ACAD8B:\ +F6286D8D4FD9D8B373C7ACAACC517DD041E6E8A69578CD444B22579B4D3C3EBE:\ +621D087684EF405E7E49478F145FBD45 + +707ED22B1DE93A11A851C0B14B1CC4B09E6431FAF7F11E97730D1E9F5C729D9DF12E4DFA\ +53E88A5F8507FAD0AB721510E02EEBDB84EF9B34120FFA1FD80C5C0C3503AD02AF96E4F4\ +66C462C3B4F3D26C78DF8C08A551DC39AAAF7EE05B13D2E1B80DA5A1A532B13EF0D1B065\ +9D2A0B43246E52CF8B6CF4EC5918769C21C51C6D1DA8DCCD2F3B0360248480C36D4F5CB8\ +317973D42FF7DE23D34329FD57B204EDD045BB87DFA5913819F15C6D5049DF1DBCC696D2\ +4C34160249CD84AE0E94C9D50A5EC764C48B26C7C8E28BBBF418525F9FEB0DE1:\ +4F9221B68E45395D5C923C4A6F96826018E207CEECC5DF1560A7587D15427B75FF3188E2\ +19D5EA5F92F909B129D6CDA2AAFD9D52B8B0C05B9E9363E8117E9996923ED6C59287108D\ +A2F5FF3451823362B2CEAB17E862E622437A990F7B23A9FDB6791A9FBFC1C06214673C92\ +41164044EFCC6439AE42079D3B1130320A878581D2EBD264D4FB53ADF5A60091695636F3\ +EB58B73A3342D3CDF833F7E82D6EE1FAF65E327DBE4350307CBD631042517C448F91603F\ +2BD6038FBB847B53F98A8DF30205022C613365C8C69CC55C6B911CF3D5567004:\ +6886D97D7FB73175DA93375F14FBA49AAA7ABE901751EB42CD243B568AD6DC18:\ +9F9E1F292C86CFB45E0334700755C190 + +0612DA958E54589E58F7C2E70F374D0CC47109B326598E46FCFD23553E3D84C703475618\ +68DD38847E0096E2FDD36CE8997820679ECD5219FA16CC9FF0F2DF8AACF9116E6FC9F926\ +1674EAAC3142DE0B9941DE77172FCA477759531B77348D914017B5E1896DD87B3DC0CB84\ +4CF642C1919D25E21E2A94977065621A4433265F590DE23612FA6B16B031F6DB3648A42F\ +57DB126211F6FE7231849B5B54694DD736E512D1EEF0001BDD94DA84AF47C71FF61F4951\ +019CBFFAB709278DBCB60F17EBAFA7DDFC071ADB89EDD569CF4A8C7D566FF1B7E20CB0CE:\ +67943CFCC4B795A311DCDACCFDBE44FA84FAFD87889892F0410166017B032B78CE7B96D0\ +3D00222424E0D363DD321634F4D151E1E03C357BEE8AFC7C561E8629EC55EB52567EFC8D\ +906C2AF0E4C385A0011CCB9E254834E55F7870F10BB563BF0A732CD6AC6F8DDF19C0D3E9\ +AF3A7F54C38E66BBDF3CF7A00361FEC2F5A7EBEA03C4C42AAA0A74F11EC51D3F5E1F78B9\ +0B09CB524F7A5DC8CD561E15EB866449F4893FD49346290A63A8D478A0C5ACED66550BF6\ +4D2A0CC5AE29886DA6DF798D8EDA7258B74BECD3094D6E83A61A9288EA1A8D0FA91E6F19:\ +F1F03359760DEFBA1ED11309F0C1D27A311FA4DEC398107B2D0AB2E0EAA895D2:\ +2FF7028F78B7F5623CBE7D592EE5603A + +4202E5DAF05E4E2DA055A9B76CA4C678A5D7F1B5F130E68389A57A52AD82B1A08FD35CD6\ +1832A0964A5C66F91E9F7826DEA9C78F5257206DD3A78C099768524D1E3B01306A9AF70F\ +2FA7DFB02F9717C2C9D7CF037603B96AFB5B9A5C832FFD86793C0228F9F38593338D92FB\ +70CFE3EB0B4B0E149E52ECD784E0756C1934B3DE03B439292052C21B40CB5D39FDD7BF3D\ +81C314F927C6EF03FB4270BD1DFB796EF59F887AB566D2AC112C1EBBE1C98679D7F0B724\ +94BAA6735FBA58D3CD125ED42272E34A9D51407D5550FD3DBE0E06004D31CA3B5CC1874E\ +10A60668:\ +DB896F08DC3DD1224CAA35F8D841E6174E03595794F8C623987CD275AAFD213A0622D2CA\ +B9DA6C8FB847FAD852352CE37806529A4F06A1620AB065D157E8992981BC74DAAE1AAD30\ +0447E720146174D75C8C09F1A47D307C6492D93E7035A081D4B47EAA116BA2F2643CDF4B\ +26EE8B82BC90FAAE8BEDC463B93F2ABE99BB7A1FECFF8FBAADF907FDDC34AFE59484DFEA\ +97937C02EDECBD1F3827518F3183FAEE67798726A220624A7C5AFBCDCABA3ACCA8862B31\ +9DE90F4C59C13EF1B8FF43DDACBC0A18548F148676034A3D71E928B1D25609C539C3203B\ +7055498D:\ +8739533FF38CD3C2A5969CDF010BE33299B5772DA0F4A56FEFBCFB4C187A398B:\ +C28792697951BA0551162D5FAC70775D + +2A797C4F230EBA8E8D560B141D6F7498036F7C54D326F67E8A0894E7C7DEBB49A717E2FF\ +12E5020B8F4F3D00236075334BC1C1BE18609339FFE59A60DBCCA006446B05FF8C296E57\ +FCABA4121656638EB88214BB0252941598EAEE42966CC162D78D0DA6D54C037876AE0931\ +F94BA160CD17DE6FAFFACAA68C5F765CE64BC85B4B132366618C723B04ACBE5392991A1D\ +1570BB5D3FF257256473297D9DE7FA8901F69B8603C9BBC267E3629A33A6A79697CE70B9\ +37E6B15BC6DEE6C0298CEB375B40DB4E0FCEAF71D5302680DE2875F14750E45771D5538A\ +CA54A19EE9E438CB:\ +B0C2C84FA758C6144BC07E436E7C4A7FD9279C35256524329930F5934B6D7CF4BCE3C7ED\ +4D6603794393D85C28E4DB61D4FCD17A90EE2AA4E6C29E99FD6C4BE9E245329D4F33127F\ +05C903EE1360DC713132281D67D23BA2B738A0F8C66A071DD9C31A19E13489EB8681CA99\ +84B3020F497CC66E5CBB3979F09B0A7C5A043150D846EFE148E7871A45FA8DAC26416BE6\ +936E5D3289A5B7AB77762726F7E4EA82D00D3123183BAF7CC146C761A7FC483055C0D687\ +944BCF9072377A7F797EF2163FE07B7656A56083E351EF3F2026B19FF76C3162CAB2CC86\ +293C537407F0F569:\ +C7B7849FE8962C5670F745C8E26B979CCA21F1628305A75E9372A684EB8FAB87:\ +CE0C1E9870A5D615C9F6D8826D7B61A5 + +43328C5C5E30B0396CBCFC0E6BE81C49B9164FBCB9A9081CC22E223CA5CC5FD28922013E\ +4A9A95DEB0025DD15087D516FF4771182A67E2E69E55C19809A8B9BF4F77E02748DB3CD1\ +CC0718E37C0A9555E703C579F5761EE6DDC484BF619243A95BA97E8B0A5CE152F3C1D72F\ +D69519E9479F4B1C46C23194DD06050224A7C2F467BE08C7EFCB0AF1DF523E294FD7382F\ +4B60690CF7EE8B8AEC379363FF636111AD4CFEA81EF2953BF76C2C8E76DE5B29334FCD09\ +F01FD4902C1021C93BA381CEEE9ADC7CA08D18B00FB5E652839848999FABD577870DAD51\ +0E8115B01AFABDD683FB3CA1:\ +1775067911F026BEE6DAC1CB54B8FCD1AFEAAA98D610FE00C63524F9AB0EFFE7CB7861E1\ +C7B1243990514BFD92C1402305958731E5E730D2AC179916220291A604B479471A249874\ +D1B067558F0D61F29790DC82765A0C4B00DBC0AE2A3B1E608E9D1F429E64CEB08D2AC7E6\ +1DC0A3B8174D8F79CA27260991CBD7D739128012B6DF93DAD582B96603E61398BA8BEEDE\ +F70AF98CE871CB49F2557C239CD61BADE4F38E0CBE1EBDC4580B56CB1830B5A14179C55B\ +A1C3EBD60F60388B164CA51F1369900E9C3FFFDB39D0E9A594A329723CE60A21E7C87F8D\ +756EE5C92CBD45D7E5A57395:\ +BCCCB7F12DE82B841EF1C0171472BE0188C2468C8D660F268F2332530A2930DA:\ +570030C34B809C5D361636F477FA84CA + +033362424F88682DB69F71DFFB5C08A010BA4394CE1305A467B4BC7E6DFF93DFBBBD7FAB\ +DBE62567612AC8AC5581A7A506D13CB8FED0C856A89D84B4D14D98005C74616704E46CFF\ +43A878B66D1D6B3636949C19404EC55B61A1F5DBBC829AA720FB4A5D3FDB8919885E6CCC\ +35943AC13E655E4149A587C4A60DC54BEE8C64A0DF49656CD4F67FD5ABFE1A8090E48212\ +646D730B50E8255774A3A1756F63DDFBB33DC0D2EF5786B6BB6E303006A2FA3217143CD9\ +237D15F24FF27DF41A9099E53432EBCFBEAA0ECD5FD419D736857E57F8917DAB5C20274B\ +F0F61075BE07EC5383BDF320C8F04FE4:\ +11C73FFB2F85FE26E087184A4E7D0E74CA4769A072EC036EAAA0162984CBF53979926FC7\ +09BB59158685C6F131BB3E79886D13F0A644A420D14DE9DD497FBBF5C8CAF27E6C2CFD83\ +CFE6A5219EEB8B29DB9D2722FD7E1004BD1152F6698C4DADEC589BBBFA3EF96BCF4E90CB\ +1395EABA2F1D90D5B2F81F312F2AF94583B4F3A8DEF1EAB26FC8EC9C4C2663F4CBF856B1\ +BA593A3E3F54B3D3831E24B44C7A5217695F3FD36D834DF32488DF461A118A93264B2E66\ +57DDC66D246720E94EACD77ECF23642A036229143868ABD20F3B1FAE1B852C9669CCB0B3\ +334FBA0D8FEAFDD56D03E52F5D136E87:\ +2CFCC0880B1BCB48651602B2F653034A6B8406B143AED550F85F122DA3BC6E28:\ +68A553188B539B46214ADE17802A5ADB + +9481ACE7C47FEC3A22B41B81E1A72363D4F4EED3CB0C93200769415B4779755982EA26E0\ +F6363C973A7C59A43FD6CC4B2D1857EB38B5AE5BEA22DA4781AC36F5559A2A2A8EC111AC\ +33275AEB3863B2A7CAEF572A16523A1231FACDF0FEBAF9305B658A4E7B0CCB9A424D5838\ +4B385132389D5545ED6D2BDC3D615D229ACFBCE60205CE1119322C642F4D81ADAEA50995\ +E4DEEB23D9976A1FF4A9C8CE7F0CC7DE657690F9651E53DE4E58561E9570CC4526FE03DD\ +686BA1AF9557718D38641B080592C9BFB2FEAEE56AFACB4F811439FE29AD6BA8D6F0ACC3\ +FE3836369CE06AEAC64898DB676EA7640D7A7BE6:\ +8217EAB21AA0D8A541AB0CE258E96EDD82866A5460455B82C339F5157C2B159FD8CA8AF0\ +413BDB5995EBEE6AB6E1F8FBB03C67B086DD2E6AE05E0B37ECB43EC2C77E9510F24BA1D6\ +E5D4906A10BEDEC2D3ABC09019274E8D09CD3921B3DF7F9EA607011655C684C3FD435747\ +6F97C1FE8314A80AE372EC4C4B19B5D34469E66A94DDF0E0C5546A290FE42A3D00F071B5\ +846DDF4D88E320E4AFF2CE3D650DDCE965C16C3943F1EA5A63D9696F8DCA6D7D65C3FAA6\ +157549B214FC3B44E6C62D124EA327E97A91126256CC475A5C533CAF2EB3F6B08769436E\ +CCD52D2AB31A87E1E09D00D2F835BF9A7356EF71:\ +30A6450164DA25B43CA6DB430F827299AB79CA4A52C636C690F7BBDF82BA9B0E:\ +4A87D1FFB56ADFC374C09B2F8D021CE8 + +3F5E7DEA03EC52DD0CDB0030F676EDF2EC5B91C788D1AC9F8E88391FED510CC64123E47A\ +C2B685E5387365DC98DA305A832BE09C50F2E3E5B97E02C92F92EFCE59DD0A18E1227661\ +719B54397B0367359A1EE476E8106D2CAF3988E95BCA0947E2411574E3E61D79BC8C6FF5\ +F7D806BDA98E0C69E4F44F70E9B2F1178DA75DB504D3F8096AE002E2C7C36E95EA3D37CA\ +3807E760424D022697FD763B1B85E4D4D15D95153BFA3F74BADF46EC1906B1904D250E98\ +4D7CB5314EADD248A801373FBE2D9EF1B9D82AB3FB0C2CA0F3F9EC0F83268EB2464E40E0\ +C40EEEFC1B9C4859A357CC62C5537783D7437E6509689C6A:\ +E4E2000ACFA0762A90E16CE545060CB60961F69586A8845D37709DA643894EB7BB29B2A0\ +69E0533EABEA770AAEF101CEC381983F59278E7EF2A55B190F7B758DD97050315B3EF563\ +CF92CF9D2CF955F266C77AC4AC8BD7BBE39CD4F5EE6E57854C8F2DDC6462889E1F02DF8A\ +7C1AC02B65423A17299973745C7C4F17E4579F514F199932D98062E3F0E141A8133CD974\ +A4B1C8A066C4800CDDE54424F4BE19C4E0099A9AAF11692C27E182AA55DEF8A439A746E9\ +DDB83F674F76F297BBE8C1DD7F4A4582260DB38C14E6FC40FB1DD429FAD55769A89BCCF0\ +0677FBE04B07C5BF6380AC4DCF47FFE08AB15370ACF4082A:\ +9361EA127351940052051851106E32E21B5B74CAC5EE2C65A478DC07962653D1:\ +F6159606256712C7DCBB2F3E8ECEE258 + +378FB5CB6B0FAD01796C73A850C8EF78AF71CB2AAC0CF7FE9EDB58D64EFA6D138FB8FF48\ +4500C5E15F8013ED56BADC846334DB7AA6DD1B0C55BCD1A32B93A86B54B74D06F3224369\ +D5E2ABF310A13D76CD3C0E037E161047CCDB49C1F117097AB42E0CEEFB4B09EA86305C72\ +D1627D53C5D8DB79070F20BADF51DAC0F6D019C7520DF841978F0249E24F995D4C0823A5\ +CA663B67B25EEBB8A38A95D27F44E425DE53CF55E5E3811CADDB9C0AD3C415587DB968FB\ +1F2D93D3B02D5628BE64E09AAA0A79E9EB6B72D0088554E77574315F1152F489ECCC4B8B\ +9705B10C96CDF2368DD61D8A345570B4751DB4533643C8F10CA2E5E9:\ +6EC13D2297C89EBE84380FD858E68FEC5E09BA9F4974C03B0C1A098C42644170358B7926\ +01D88B40CDF56ABD6A2D8B7CA430AF87EC349C2B11D44731A0C219F0DF310832ECA798BE\ +E87C293C8834CD74724E96A6D7A1DFCEFA893DA180CC2CA8465274D176BB0D25B1FCD04A\ +3142EDE3B74A6D3E1ED86F3289DED1E37D32B9925C8BB51913B2850E5DA43159D4F70F64\ +06F5BCF600B1AFB2244BFEED3B40303C58892BA8A59151F8E2649964E767D918771E2681\ +26CE88156C4FA319F65CB1E2909F5A196399B45EF0B040C3DCA7E79232E4782041C7E6B6\ +5C9C82D8B4517B469493A46831B9E9094AEC31639E353F40D3AF1488:\ +2377222F39987D62CE8CB5F64E88437543E20EBB58F2DCB159E0AECAF439217D:\ +2DAD0FE823C71638F1910AB8D8924C87 + +41E99B44C7C94FD5B8978507A99DFCF6EC7A49304EC6099AD1C38DBF8BE918860AB5C37B\ +D13253B763406AA6DA1CE6779CED6F7F7B222CD51967BD3B61FA48F6B65B96891E34FB58\ +3E0935454ADCB3CF6419216B798A7C0CE5402A3232510940839D4DCA082247505CD68D73\ +B1AE4E352B9A95F6CD68CACF68F28A525CC3DAA1504DE85B51CFDC3B693DFAD28D4ED86B\ +70B93B02FAAA0BFE452544C81ADEEF99A59378CE0625234EA69E9F69ED52D5FBB6687F9E\ +E248479E1B29ACF0CC3BE7BA5B77537C29CAB662B2DD7D8937B9DEE577E7C8DE85D3CEF3\ +0912FF62687756C6F978FBB147E6B27E923C62F9A38BD7F50D8801E676FA07DA:\ +BC7838EBF0287786D89BAAEBA8ECA378E898BB36A6D3D6CC125938D71768BA704E30F9FB\ +7B09A43D85786790FCEEBB46A2A341C4EA50AEEFF3DC57005DFD7BE9C4052AB3CAB38B11\ +221EA39EA778AC6F4111CD1978E5D467301BC7ADDC54D084F36652A9AD3EDB8D70AE6380\ +3B077A39CF064017DC2A8CED0E4B1A7D6FAB58B0FC92684778B7B3F5D76477CAB7C6C1C6\ +AE6BCA1F661CF26DFEFCD1DB5DF58F1358D38406E3D880F30E43E1837132B5DEE65EC09B\ +7622CDA1F52A78F8EDF870D2AF375C7526C70E43FF650B8EDCF6A35D02CA479DD560A672\ +45C7087D0376C9915777FCCB390109115AAE52C4512ADAC046C8C1E9092F3018:\ +19F394E4AF235F4BDD3F0798E904A2E114041B351F0D71C5BB269845BB53D4B9:\ +093E57768A6107B8D6F31A083B23B3FE + +20143BDD828F687A93266C2E489909BFD6D85884A40018082FDE227841647D162DAFC241\ +40580495B6E0C393CFE2BBE80615C87CBF5E057D74A4CD7589DE69E136870A24AE67F9F0\ +FC7B92369903718B9268500155ABBD6C8D0E81FB1104403A02A56FC82F1DE4137EBA1433\ +AAD9CE7B34198ABE7D9845DC462DBB4FC6DA4F937EBEAC139339B405ABA51BFC9B06B38C\ +BF17352F47C6EF3968F06305123888130738B887911567A28DEFBCE943D18C73ACBE920C\ +386143E0B6B2C9EA30C84A7E4196481F93395C8BECE5F9B341725DA7883DD74792AD0140\ +7A05BE7A2121AFB2E9EAEBBA7574F9582D0455571A077603A511ABBEF9EABEF4553A48EF:\ +FC293D577FE018127C31A901490F19DD72D0A3212C828EA530B256E563874E03C7003668\ +84568B2F58B0478B8953F5A667E070BDC386404C47A45A862626D7F621C5E87C3F48A15B\ +8F7DFA5EC168ACBEE32E08551DC7AB5826F42A75CE8A0A61BB9E1F4AD5BE53AC87687961\ +388BB809ECEFDDD93782A956F9976242B20B1C2B5EAE31D28B48A44337AC677C6B865D89\ +954E1159353FCFA1741C287FEE15473CB4004E400FAF336995004964A79E2EB0FDF48C2E\ +A09120126443E8771F9700718BC94E5070DA8DAC17BB3F73555F3942AAC1C2830371D641\ +7EE51EBCB1ACB8B4C74BAAE38E6CED7F7622388FBE2B2153DB6945B77AADCF7DC99502D6:\ +BA516D7A4B7638995562CE54FEFC84B6DFB4B8A81A03F24BB065B060E4FA2966:\ +23C93FBB6EF742A576769819A5BC6AC3 + # MARKER: Cipher Modes (Decryption) # Cipher mode format is plaintext:ciphertext:key:iv @@ -24360,6 +25419,37 @@ E5C7CDDE872BF27C43E934008C389C0F683788499A7C05F662C16A27E4FCF277:\ 4E6F77206973207468652074696D6520666F7220616C6C20:\ 0123456789ABCDEF:1234567890ABCDEF +[Serpent/ECB/NoPadding] +B2288B968AE8B08648D1CE9606FD992D717EB02EB81A2E939D54ACA91087112D\ +0D809C5EE82F477EBA7B956DBB23463B0F0190D616F5294112FFB7884E8B37F9\ +41BA1B505386B7428B88338188F7E718A3348230BF5CFA552F88D22463D9703A\ +115351622E016BCA26918D17E13225F67EE4E3F2C46FE52ECBDA044C585717DC\ +563A8403FF5309D62370B1DCF5A11EDD2F7D73602B70CD2553E44C1D3F170126\ +155BBD9BE3A965B345E834718F651CEF6CC65E8C5C566E894817350F497816F1\ +EEFA51FC91FEBB6E9F8CB141CC0EB6AF3C6F8380CBD3C996167F2F0E90E71B75\ +6C87EB62A4975356B28DCBF6A64A0BD107206D48FE6DBE19D50314B90AC87B83\ +35706F9B26007071AD8105CFAA1C1E2FF7FEAE5CEC4D11477F24E6B200906870\ +3C0E29E2950F2AC2DACD63DEEB5C7EFA9FDB9F3B740563D5518287DC981FC9CB\ +46D4B5A5A86FEC08FE70D18297DCF51072DDBE038DA040EBB12C509F5940A212\ +DDEB59F02132BE4581FC23EABAA960D6341D9352E36DFD6E4EAF0F6F439BC8CE\ +73A9AB3164FF30350F2DC08E939A104D6DF0C2C28F8E2D44468A61278BB6B429\ +4DAE45AE0CAA032FC97CD4D8C57FB83BBA8AFCAE22070BC882D3A42B38A09E65:\ +D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78E\ +D29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78E\ +D29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78E\ +D29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78E\ +D29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871\ +D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871\ +D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871\ +D29D576F315C5C58126F660D6D8C28712D62A890315C5C58126F660D6D8C2871\ +AA26D561F567520E8AE47528C24C18D731A2193D9A97FED6922B17AAA6372B74\ +BE5DEBD559E303C9C92B174A5107BBFEB626D8F65EDCCDF3AEE475C8A1837722\ +41DDE7C1F1631F5FDED4F42746471BD651D238BA86176EFE39E4695AAEB73B52\ +EA5926CADAD8018962E469BA920CB8BF1EA9062E4D9CEDD5FAD4F4C7990367A4\ +B966E5C5D2277288C61B96A559CC84AFB6A6583C5AACFCD6212B0BD8AEF3C6A9\ +A11DDBD175639341052B0B384678D8D9352299B71DD880E29D1B96452DB86540:\ +00000000000000000000000000000000 + [RC5(8)/CBC/PKCS7] 7875DBF6738C64788F34C3C681C99695:FFFFFFFFFFFFFFFF:0102030405:0000000000000000 7875DBF6738C64787CB3F1DF34F948117FD1A023A5BBA217:\ diff --git a/configure.py b/configure.py index 821092151..97fd44816 100755 --- a/configure.py +++ b/configure.py @@ -9,6 +9,8 @@ Tested with CPython 2.4, 2.5, 2.6 - OK Jython 2.5 - Target detection does not work (use --os and --cpu) + CPython 2.3 and earlier are not supported + Has not been tested with IronPython or PyPy """ @@ -34,10 +36,10 @@ class BuildConfigurationInformation(object): Version information """ version_major = 1 - version_minor = 8 - version_patch = 5 - version_so_patch = 5 - version_suffix = '-rc1' + version_minor = 9 + version_patch = 0 + version_so_patch = 0 + version_suffix = '-pre' version_string = '%d.%d.%d%s' % ( version_major, version_minor, version_patch, version_suffix) @@ -113,6 +115,15 @@ def process_command_line(args): target_group.add_option('--with-endian', metavar='ORDER', default=None, help='override guess of CPU byte order') + target_group.add_option('--with-unaligned-mem', + dest='unaligned_mem', action='store_true', + default=None, + help='enable unaligned memory accesses') + + target_group.add_option('--without-unaligned-mem', + dest='unaligned_mem', action='store_false', + help=SUPPRESS_HELP) + build_group = OptionGroup(parser, 'Build options') build_group.add_option('--enable-shared', dest='build_shared_lib', @@ -162,6 +173,8 @@ def process_command_line(args): mods_group.add_option('--disable-modules', dest='disabled_modules', metavar='MODS', action='append', default=[], help='disable specific modules') + mods_group.add_option('--no-autoload', action='store_true', default=False, + help='disable automatic loading') for mod in ['openssl', 'gnump', 'bzip2', 'zlib']: @@ -400,18 +413,27 @@ 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): + return cpu_name.upper().replace('.', '').replace('-', '_') + if self.basename != target_submodel: - macros.append('TARGET_CPU_IS_%s' % (target_submodel.upper())) + macros.append('TARGET_CPU_IS_%s' % ( + form_cpu_macro(target_submodel))) if with_endian: macros.append('TARGET_CPU_IS_%s_ENDIAN' % (with_endian.upper())) elif self.endian != None: macros.append('TARGET_CPU_IS_%s_ENDIAN' % (self.endian.upper())) - macros.append('TARGET_UNALIGNED_LOADSTORE_OK %d' % (self.unaligned_ok)) + if unaligned_ok is None: + unaligned_ok = self.unaligned_ok + + if unaligned_ok: + logging.info('Assuming unaligned memory access works on this CPU') + macros.append('TARGET_UNALIGNED_LOADSTORE_OK %d' % (unaligned_ok)) return macros @@ -717,7 +739,8 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): cc.defines(options.with_tr1)), 'target_cpu_defines': make_cpp_macros( - arch.defines(options.cpu, options.with_endian)), + arch.defines(options.cpu, options.with_endian, + options.unaligned_mem)), 'include_files': makefile_list(build_config.headers), @@ -748,9 +771,11 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): 'static_suffix': osinfo.static_suffix, 'so_suffix': osinfo.so_suffix, - 'botan_config': prefix_with_build_dir('botan-config'), + 'botan_config': prefix_with_build_dir( + os.path.join(build_config.build_dir, 'botan-config')), 'botan_pkgconfig': prefix_with_build_dir( - build_config.pkg_config_file()), + os.path.join(build_config.build_dir, + build_config.pkg_config_file())), 'doc_files': makefile_list(build_config.doc_files()), @@ -791,13 +816,27 @@ def choose_modules_to_use(options, modules): cannot_use_because(modname, 'loaded on request only') elif module.load_on == 'dep': maybe_dep.append(modname) - elif module.load_on in ['auto', 'asm_ok']: - if module.load_on == 'asm_ok' and not options.asm_ok: - cannot_use_because(modname, 'uses assembly and --disable-asm set') + + elif module.load_on == 'always': + to_load.append(modname) + + elif module.load_on == 'asm_ok': + if options.asm_ok: + if options.no_autoload: + maybe_dep.append(modname) + else: + to_load.append(modname) + else: + cannot_use_because(modname, + 'uses assembly and --disable-asm set') + elif module.load_on == 'auto': + if options.no_autoload: + maybe_dep.append(modname) else: to_load.append(modname) else: - logging.warning('Unknown load_on %s in %s' % (module.load_on, modname)) + logging.warning('Unknown load_on %s in %s' % ( + module.load_on, modname)) dependency_failure = True @@ -837,6 +876,8 @@ def choose_modules_to_use(options, modules): logging.info('Skipping mod because %s - %s' % ( reason, ' '.join(disabled_mods))) + logging.debug('Loading modules %s', ' '.join(sorted(to_load))) + return [modules[mod] for mod in to_load] """ @@ -881,6 +922,11 @@ def setup_build(build_config, options, template_vars): Copy or link the file, depending on what the platform offers """ def portable_symlink(filename, target_dir): + + if not os.access(filename, os.R_OK): + logging.warning('Missing file %s' % (filename)) + return + if 'symlink' in os.__dict__: def count_dirs(dir, accum = 0): if dir == '' or dir == os.path.curdir: @@ -963,7 +1009,8 @@ def main(argv = None): if argv is None: argv = sys.argv - logging.basicConfig(stream = sys.stdout, format = '%(message)s', + logging.basicConfig(stream = sys.stdout, + format = '%(levelname) 7s: %(message)s', level = logging.INFO) logging.debug('%s invoked with options "%s"' % ( @@ -1027,19 +1074,24 @@ def main(argv = None): if options.compiler == 'gcc': def is_64bit_arch(arch): - if arch == 'alpha' or arch.endswith('64'): + if arch.endswith('64') or arch in ['alpha', 's390x']: return True return False if not is_64bit_arch(options.arch) and not options.dumb_gcc: - gcc_version = ''.join( - subprocess.Popen(['g++', '-v'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE).communicate()) - - if re.search('(4\.[01234]\.)|(3\.[34]\.)|(2\.95\.[0-4])', - gcc_version): - options.dumb_gcc = True + try: + + matching_version = '(4\.[01234]\.)|(3\.[34]\.)|(2\.95\.[0-4])' + + gcc_version = ''.join( + subprocess.Popen(['g++', '-v'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE).communicate()) + + if re.search(matching_version, gcc_version): + options.dumb_gcc = True + except OSError, e: + logging.info('Could not execute GCC for version check') if options.dumb_gcc is True: logging.info('Setting -fpermissive to work around gcc bug') diff --git a/doc/api.tex b/doc/api.tex index d52005f49..d86fa79e2 100644 --- a/doc/api.tex +++ b/doc/api.tex @@ -12,7 +12,7 @@ \title{\textbf{Botan API Reference}} \author{} -\date{2009/2/10} +\date{2009/2/19} \newcommand{\filename}[1]{\texttt{#1}} \newcommand{\manpage}[2]{\texttt{#1}(#2)} @@ -41,7 +41,7 @@ \pagebreak \section{Introduction} -Botan is a C++ library which attempts to provide the most common +Botan is a C++ library that attempts to provide the most common cryptographic algorithms and operations in an easy to use, efficient, and portable way. It runs on a wide variety of systems, and can be used with a number of different compilers. @@ -156,7 +156,7 @@ should be used with the \filename{botan/} prefix in your actual code. \subsection{Initializing the Library} -There are a set of core services which the library needs access to +There is a set of core services that the library needs access to while it is performing requests. To ensure these are set up, you must create a \type{LibraryInitializer} object (usually called 'init' in Botan example code; 'botan\_library' or 'botan\_init' may make more @@ -177,9 +177,9 @@ is: at the start of your \texttt{main}. -The constructor takes an optional string which specifies arguments. +The constructor takes an optional string that specifies arguments. Currently the only possible argument is ``thread\_safe'', which must -have an boolean argument (for instance ``thread\_safe=false'' or +have an Boolean argument (for instance ``thread\_safe=false'' or ``thread\_safe=true''). If ``thread\_safe'' is specified as true the library will attempt to register a mutex type to properly guard access to shared resources. However these locks do not protect individual @@ -197,7 +197,7 @@ static member functions of \type{LibraryInitializer}, called \type{LibraryInitializer} merely provides a convenient RAII wrapper for the operations (thus for the internal library state as well). -\subsection{Gotchas} +\subsection{Pitfalls} There are a few things to watch out for to prevent problems when using Botan. @@ -207,7 +207,7 @@ before the library is initialized. Many Botan objects will, in their constructor, make one or more calls into the library global state object. Access to this object is checked, so an exception should be thrown (rather than a memory access violation or undetected -uninitialized object access). A rough equivalent which will work is to +uninitialized object access). A rough equivalent that will work is to keep a global pointer to the object, initializing it after creating your \type{LibraryInitializer}. Merely making the \type{LibraryInitializer} also global will probably not help, because @@ -240,7 +240,7 @@ wondering what went wrong. Many common uses of cryptography involve processing one or more streams of data (be it from sockets, files, or a hardware device). -Botan provides services which make setting up data flows through +Botan provides services that make setting up data flows through various operations, such as compression, encryption, and base64 encoding. Each of these operations is implemented in what are called \emph{filters} in Botan. A set of filters are created and placed into @@ -249,7 +249,7 @@ reaches the end, where the output is collected for retrieval. If you're familiar with the Unix shell environment, this design will sound quite familiar. -Here is an example which uses a pipe to base64 encode some strings: +Here is an example that uses a pipe to base64 encode some strings: \begin{verbatim} Pipe pipe(new Base64_Encoder); // pipe owns the pointer @@ -383,13 +383,13 @@ perform more than one operation on it (\ie, encrypt it with Serpent and calculate the SHA-256 hash of the plaintext at the same time). That's where \type{Fork} comes in. \type{Fork} is a filter that takes input and passes it on to \emph{one or more} \type{Filter}s -which are attached to it. \type{Fork} changes the nature of the pipe +that are attached to it. \type{Fork} changes the nature of the pipe system completely. Instead of being a linked list, it becomes a tree. Each \type{Filter} in the fork is given its own output buffer, and thus its own message. For example, if you had previously written two messages into a \type{Pipe}, then you start a new one with a -\type{Fork} which has three paths of \type{Filter}'s inside it, you +\type{Fork} that has three paths of \type{Filter}'s inside it, you add three new messages to the \type{Pipe}. The data you put into the \type{Pipe} is duplicated and sent into each set of \type{Filter}s, and the eventual output is placed into a dedicated message slot in the @@ -421,7 +421,7 @@ NULL pointers), message 2 will be the output of the second allocated in a top to bottom fashion, when looked at on the screen. However, note that there could be potential for bugs if this is not anticipated. For example, if your code is passed a \type{Filter}, and you assume it is a -``normal'' one which only uses one message, your message offsets would be +``normal'' one that only uses one message, your message offsets would be wrong, leading to some confusion during output. If Fork's first argument is a null pointer, but a later argument is @@ -451,7 +451,7 @@ Here we wanted to not only decrypt the message, but send the decrypted text through an additional computation, in order to compute the authentication code. -Any \type{Filter}s which are attached to the \type{Pipe} after the +Any \type{Filter}s that are attached to the \type{Pipe} after the \type{Fork} are implicitly attached onto the first branch created by the fork. For example, let's say you created this \type{Pipe}: @@ -476,7 +476,7 @@ out of a function, or to a \type{Fork} constructor. You can call \type{Chain}'s constructor with up to 4 \type{Filter*}s (they will be added in order), or with an array of \type{Filter*}s and -a \type{u32bit} which tells \type{Chain} how many \type{Filter*}s are +a \type{u32bit} that tells \type{Chain} how many \type{Filter*}s are in the array (again, they will be attached in order). Here's the example from the last section, using chain instead of relying on the obscure rule that version used. @@ -497,7 +497,7 @@ By default, \type{Pipe} will do nothing at all; any input placed into the \type{Pipe} will be read back unchanged. Obviously, this has limited utility, and presumably you want to use one or more \type{Filter}s to somehow process the data. First, you can choose a -set of \type{Filter}s to initialize the \type{Pipe} with via the +set of \type{Filter}s to initialize the \type{Pipe} via the constructor. You can pass it either a set of up to 4 \type{Filter*}s, or a pre-defined array and a length: @@ -523,8 +523,8 @@ use; that is, either before calling \function{start\_msg}, or after have been made yet). The function \function{reset}() simply removes all the \type{Filter}s -which the \type{Pipe} is currently using~--~it is reset to an -initialize, ``empty'' state. Any data which is being retained by the +that the \type{Pipe} is currently using~--~it is reset to an +initialize, ``empty'' state. Any data that is being retained by the \type{Pipe} is retained after a \function{reset}(), and \function{reset}() does not affect the message numbers (discussed later). @@ -533,7 +533,7 @@ Calling \function{prepend} and \function{append} will either prepend or append the passed \type{Filter} object to the list of transformations. For example, if you \function{prepend} a \type{Filter} implementing encryption, and the \type{Pipe} already had -a \type{Filter} which hex encoded the input, then the next set of +a \type{Filter} that hex encoded the input, then the next set of input would be first encrypted, then hex encoded. Alternately, if you called \function{append}, then the input would be first be hex encoded, and then encrypted (which is not terribly useful in this @@ -557,7 +557,7 @@ contains. Writes at any other time are invalid, and will result in an exception. As to writing, you can call any of the functions called \function{write}(), -which can take any of: a \type{byte[]}/\type{u32bit} pair, a +that can take any of: a \type{byte[]}/\type{u32bit} pair, a \type{SecureVector<byte>}, a \type{std::string}, a \type{DataSource\&}, or a single \type{byte}. @@ -566,7 +566,7 @@ you can use the \function{process\_msg} series of functions, which start a message, write their argument into the \type{Pipe}, and then end the message. In this case you would not make any explicit calls to \function{start\_msg}/\function{end\_msg}. The version of \function{write} -which takes a single \type{byte} is not supported by \function{process\_msg}, +that takes a single \type{byte} is not supported by \function{process\_msg}, but all the other variants are. \type{Pipe} can also be used with the \verb|>>| operator, and will accept a @@ -579,7 +579,7 @@ read into the \type{Pipe}. Retrieving the processed data from a \type{Pipe} is a bit more complicated, for various reasons. In particular, because \type{Pipe} will separate each message into a separate buffer, you have to be able to retrieve data from each message -independently. Each of \type{Pipe}'s read functions has a final parameter which +independently. Each of \type{Pipe}'s read functions has a final parameter that specifies what message to read from (as a 32-bit integer). If this parameter is set to \type{Pipe::DEFAULT\_MESSAGE}, it will read the current default message (\type{DEFAULT\_MESSAGE} is also the default value of this parameter). The @@ -598,7 +598,7 @@ destructive operation with a \type{Pipe}). There are also the functions \type{SecureVector<byte>} \function{read\_all}(), and \type{std::string} \function{read\_all\_as\_string}(), which return the entire contents of the message, either as a memory buffer, or a -\type{std::string} (which is generally only useful is the \type{Pipe} has +\type{std::string} (which is generally only useful if the \type{Pipe} has encoded the message into a text string, such as when a \type{Base64\_Encoder} is used). @@ -617,7 +617,7 @@ using the output operator. \subsection{A Filter Example} -Here is some code which takes one or more filenames in \arg{argv} and +Here is some code that takes one or more filenames in \arg{argv} and calculates the result of several hash functions for each file. The complete program can be found as \filename{hasher.cpp} in the Botan distribution. For brevity, most error checking has been removed. @@ -708,8 +708,8 @@ Here's a example: pipe.end_msg(); \end{verbatim} -There are some requirements to using \type{Keyed\_Filter} which you must -follow. If you call \function{set\_key} or \function{set\_iv} on a filter which +There are some requirements to using \type{Keyed\_Filter} that you must +follow. If you call \function{set\_key} or \function{set\_iv} on a filter that is owned by a \type{Pipe}, you must do so while the \type{Pipe} is ``unlocked''. This refers to the times when no messages are being processed by \type{Pipe} -- either before \type{Pipe}'s \function{start\_msg} is called, or @@ -819,7 +819,7 @@ exceptionally long, strange, and probably useless name There are four classes in this category, \type{PK\_Encryptor\_Filter}, \type{PK\_Decryptor\_Filter}, \type{PK\_Signer\_Filter}, and \type{PK\_Verifier\_Filter}. Each takes a pointer to an object of the -appropriate type (\type{PK\_Encryptor}, \type{PK\_Decryptor}, etc) which is +appropriate type (\type{PK\_Encryptor}, \type{PK\_Decryptor}, etc) that is deleted by the destructor. These classes are found in \filename{pk\_filts.h}. Three of these, for encryption, decryption, and signing are pretty much @@ -845,7 +845,7 @@ Cryptography'' in this manual. \subsubsection{Encoders} Often you want your data to be in some form of text (for sending over channels -which aren't 8-bit clean, printing it, etc). The filters \type{Hex\_Encoder} +that aren't 8-bit clean, printing it, etc). The filters \type{Hex\_Encoder} and \type{Base64\_Encoder} will convert arbitrary binary data into hex or base64 formats. Not surprisingly, you can use \type{Hex\_Decoder} and \type{Base64\_Decoder} to convert it back into its original form. @@ -929,8 +929,8 @@ Additionally, if necessary, filters can define a constructor that takes any needed arguments, and a destructor to deal with deallocating memory, closing files, etc. -There is also a \type{BufferingFilter} class (in \filename{buf\_filt.h}) which -will take a message and split it up into an initial block which can be of any +There is also a \type{BufferingFilter} class (in \filename{buf\_filt.h}) that +will take a message and split it up into an initial block that can be of any size (including zero), a sequence of fixed sized blocks of any non-zero size, and last (possibly zero-sized) final block. This might make a useful base class for your filters, depending on what you have in mind. @@ -1018,12 +1018,12 @@ Most public key algorithms have limitations or restrictions on their parameters. For example RSA requires an odd exponent, and algorithms based on the discrete logarithm problem need a generator $> 1$. -Each low-level public key type has a function named \function{check\_key} which -takes a \type{bool}. This function returns a boolean value that declares +Each low-level public key type has a function named \function{check\_key} that +takes a \type{bool}. This function returns a Boolean value that declares whether or not the key is valid (from an algorithmic standpoint). For example, it will check to make sure that the prime parameters of a DSA key are, in fact, prime. It does not have anything to do with the validity of the key for any -particular use, nor does it have anything to do with certificates which link a +particular use, nor does it have anything to do with certificates that link a key (which, after all, is just some numbers) with a user or other entity. If \function{check\_key}'s argument is \type{true}, then it does ``strong'' checking, which includes fairly expensive operations like primality checking. @@ -1094,7 +1094,7 @@ If you attempt an operation with a larger size than the key can support (this limit varies based on the algorithm, the key size, and the padding method used (if any)), an exception will be thrown. Alternately, you can call \function{maximum\_input\_size}, -which will return the maximum size you can safely encrypt. In fact, +that will return the maximum size you can safely encrypt. In fact, you can often encrypt an object that is one byte longer, but only if enough of the high bits of the leading byte are set to zero. Since this is pretty dicey, it's best to stick with the advertised maximum. @@ -1143,7 +1143,7 @@ a message digest function to hash the message with. Raw actually signs the input directly; if the message is too big, the signing operation will fail. Raw is not useful except in very specialized applications. -There are various interactions which make certain encoding schemes and signing +There are various interactions that make certain encoding schemes and signing algorithms more or less useful. EMSA2 is the usual method for encoding Rabin-William signatures, so for @@ -1171,7 +1171,7 @@ meaning the output of the primitive itself is returned as the key, or ``KDF1(hash)'' or ``KDF2(hash)'' where ``hash'' is any string you happen to like (hopefully you like strings like ``SHA-256'' or ``RIPEMD-160''), or ``X9.42-PRF(keywrap)'', which uses the PRF specified in ANSI X9.42. It takes -the name or OID of the key wrap algorithm which will be used to encrypt a +the name or OID of the key wrap algorithm that will be used to encrypt a content encryption key. How key agreement generally works is that you trade public values with some @@ -1185,12 +1185,12 @@ key you want. Depending on the key derivation function you're using, you many not \emph{actually} get back a key of that size. In particular, ``Raw'' will return a number about the size of the Diffie-Hellman modulus, and KDF1 can only return -a key which is the same size as the output of the hash. KDF2, on the other +a key that is the same size as the output of the hash. KDF2, on the other hand, will always give you a key exactly as long as you request, regardless of the underlying hash used with it. The key returned is a \type{SymmetricKey}, ready to pass to a block cipher, MAC, or other symmetric algorithm. -The public value which should be used can be obtained by calling +The public value that should be used can be obtained by calling \function{public\_data}, which exists for any key that is associated with a key agreement algorithm. It returns a \type{SecureVector<byte>}. @@ -1221,7 +1221,7 @@ manual. \subsubsection{Public Keys} -The interfaces for doing either of these is quite similar. Let's look at the +The interfaces for doing either of these are quite similar. Let's look at the X.509 stuff first: \begin{verbatim} namespace X509 { @@ -1257,7 +1257,7 @@ course, the source is in fact storing a representation of a public key). The encoding used (PEM or BER) need not be specified; the format will be detected automatically. The key is allocated with \function{new}, and should be released with \function{delete} when you -are done with it. The first takes a generic \type{DataSource} which +are done with it. The first takes a generic \type{DataSource} that you have to allocate~--~the others are simple wrapper functions that take either a filename or a memory buffer. @@ -1351,11 +1351,11 @@ There may be some strange programs out there that support the v2.0 extensions to PBES1 but not PBES2; if you need to inter-operate with a program like that, use ``PBE-PKCS5v15(MD5,RC2/CBC)''. For example, OpenSSL supports this format (though since it also supports the v2.0 schemes, there is no reason not to just -use TripleDES or AES). This scheme uses a 64 bit key, which, while -significantly better than a 56 bit key, is a bit too small for comfort. +use TripleDES or AES). This scheme uses a 64-bit key that, while +significantly better than a 56-bit key, is a bit too small for comfort. -Last but not least, there are some functions which is basically identical to -\function{X509::load\_key}, which will load, and possibly decrypt, a PKCS \#8 +Last but not least, there are some functions that are basically identical to +\function{X509::load\_key} that will load, and possibly decrypt, a PKCS \#8 private key: \begin{verbatim} @@ -1393,7 +1393,7 @@ it once you are done with it. As of now Nyberg-Rueppel and Rabin-Williams keys cannot be imported or exported, because they have no official ASN.1 OID or definition. ElGamal keys can (as of Botan 1.3.8) be imported and exported, but the only other -implementation which supports the format is Peter Gutmann's Cryptlib. If you +implementation that supports the format is Peter Gutmann's Cryptlib. If you can help it, stick to RSA and DSA. \emph{Note}: Currently NR and RW are given basic ASN.1 key formats (which @@ -1401,7 +1401,7 @@ mirror DSA and RSA, respectively), which means that, if they are assigned an OID, they can be imported and exported just as easily as RSA and DSA. You can assign them an OID by putting a line in a Botan configuration file, calling \function{OIDS::add\_oid}, or editing \filename{src/policy.cpp}. Be warned that -it is possible that a future version will use a format which is different from +it is possible that a future version will use a format that is different from the current one (\ie, a newly standardized format). \pagebreak @@ -1410,8 +1410,8 @@ the current one (\ie, a newly standardized format). A certificate is essentially a binding between some identifying information of a person or other entity (called a \emph{subject}) and a public key. This binding is asserted by a signature on the certificate, which is placed there by -some authority (the \emph{issuer}) which at least claims that it knows the -subject that is named in the certificate really ``owns'' the private key +some authority (the \emph{issuer}) that at least claims that it knows the +subject named in the certificate really ``owns'' the private key corresponding to the public key in the certificate. The major certificate format in use today is X.509v3, designed by ISO and @@ -1468,13 +1468,13 @@ to accept or return a \type{std::wstring} instead of a \type{std::string}). Like the distinguished names, subject alternative names can contain a lot of things that Botan will flat out ignore (most of which you would never actually -want to use). However, there are three very useful pieces of information which +want to use). However, there are three very useful pieces of information that this extension might hold: an email address (``[email protected]''), a DNS name (``somehost.site2.com''), or a URI (``http://www.site3.com''). So, how to get the information? Simply call \function{subject\_info} with the name of the piece of information you want, and it will return a -\type{std::string} which is either empty (signifying that the certificate +\type{std::string} that is either empty (signifying that the certificate doesn't have this information), or has the information requested. There are several names for each possible item, but the most easily readable ones are: ``Name'', ``Country'', ``Organization'', ``Organizational Unit'', ``Locality'', @@ -1526,7 +1526,7 @@ compromised, or the user to which it has been assigned leaving an organization. Certificate revocation lists are an answer to this problem (though online certificate validation techniques are starting to become somewhat more popular). Essentially, every once in a while the CA will release -a CRL, listing all certificates which have been revoked. Also included is +a CRL, listing all certificates that have been revoked. Also included is various pieces of information like what time a particular certificate was revoked, and for what reason. In most systems, it is wise to support some form of certificate revocation, and CRLs handle this fairly easily. @@ -1588,8 +1588,8 @@ The versions that take a \type{DataSource\&} will add all the certificates that it can find in that source. All of them add the cert(s) to the store. The 'trusted' certificates are the -ones which you have some reason to trust are genuine. For example, say your -application is working with certificates which are owned by employees of some +ones that you have some reason to trust are genuine. For example, say your +application is working with certificates that are owned by employees of some company, and all of their certificates are signed by the company CA, whose certificate is in turned signed by a commercial root CA. What you would then do is include the certificate of the commercial CA with your application, and read @@ -1663,11 +1663,11 @@ subjectAlternativeName extension). The name and email versions take a \type{std::string}, while the SKID version takes a \type{SecureVector<byte>} containing the subject key identifier in raw binary. You can choose not to implement \function{by\_name} or \function{by\_email}, but \function{by\_SKID} -is mandatory to implement, and, currently, is the only version which is used by +is mandatory to implement, and, currently, is the only version that is used by \type{X509\_Store}. Finally, there is a method for finding CRLs, called \function{get\_crls\_for}, -which takes an \type{X509\_Certificate} object, and returns a +that takes an \type{X509\_Certificate} object, and returns a \type{std::vector} of \type{X509\_CRL}. While generally there will be only one CRL, the use of the vector makes it easy to return no CRLs (\eg, if the certificate store doesn't support retrieving them), or return multiple ones @@ -1779,7 +1779,7 @@ a CA object is done by the following constructor: X509_CA(const X509_Certificate& cert, const PKCS8_PrivateKey& key); \end{verbatim} -The private key is the private key corresponding to the public key in the the +The private key is the private key corresponding to the public key in the CA's certificate. Generally, requests for new certificates are supplied to a CA in the form on @@ -1812,8 +1812,8 @@ be used. If not, then \arg{seconds} specifies how long (in seconds) it will be until the CRL's next update time (after this time, most clients will reject the CRL as too old). -On the other hand, you may have issued a CRL before. In which case, you will -want to issue a new CRL which contains both all previously revoked +On the other hand, you may have issued a CRL before. In that case, you will +want to issue a new CRL that contains all previously revoked certificates, along with any new ones. This is done by calling the \type{X509\_CA} member function \function{update\_crl}(\type{X509\_CRL}~\arg{old\_crl}, @@ -1823,13 +1823,13 @@ CA issued, and \arg{new\_revoked} is a list of any newly revoked certificates. The function returns a new \type{X509\_CRL} to make available for clients. The semantics for the \arg{seconds} argument is the same as \function{new\_crl}. -The \type{CRL\_Entry} type is a structure which contains, at a minimum, the +The \type{CRL\_Entry} type is a structure that contains, at a minimum, the serial number of the revoked certificate. As serial numbers are never repeated, the pairing of an issuer and a serial number (should) distinctly identify any certificate. In this case, we represent the serial number as a \type{SecureVector<byte>} called \arg{serial}. There are two additional -(optional) values, an enumeration called \type{CRL\_Code} which specifies the -reason for revocation (\arg{reason}), and an object which represents the time +(optional) values, an enumeration called \type{CRL\_Code} that specifies the +reason for revocation (\arg{reason}), and an object that represents the time that the certificate became invalid (if this information is known). If you wish to remove an old entry from the CRL, insert a new entry for the @@ -1853,7 +1853,7 @@ namespace X509 { Where \arg{key} is obviously the private key you wish to use (the public key, used in the certificate itself, is extracted from the private key), and -\arg{opts} is an structure which has various bits of information which will be +\arg{opts} is an structure that has various bits of information that will be used in creating the certificate (this structure, and its use, is discussed below). This function is found in the header \filename{x509self.h}. There is an example of using this function in the \filename{self\_sig} example. @@ -1879,7 +1879,7 @@ minted X.509 certificate. There is an example of using this function in the \subsubsection{Certificate Options} So what is this \type{X509\_Cert\_Options} thing we've been passing around? -Basically, it's a bunch of information which will end up being stored into the +Basically, it's a bunch of information that will end up being stored into the certificate. This information comes in 3 major flavors: information about the subject (CA or end-user), the validity period of the certificate, and restrictions on the usage of the certificate. @@ -1891,7 +1891,7 @@ various bits of information about the user: \arg{common\_name}, many of these as possible should be filled it (especially an email address), though the only required ones are \arg{common\_name} and \arg{country}. -There is another value which is only useful when creating a PKCS \#10 request, +There is another value that is only useful when creating a PKCS \#10 request, which is called \arg{challenge}. This is a challenge password, which you can later use to request certificate revocation (\emph{if} the CA supports doing revocations in this manner). @@ -1903,7 +1903,7 @@ valid, and when it should stop being valid. If you don't set the starting validity period, it will automatically choose the current time. If you don't set the ending time, it will choose the starting time plus a default time period. The arguments to these functions specify the time in the following -format: ``2002/11/27 1:50:14''. The time is in 24 hour format, and the date is +format: ``2002/11/27 1:50:14''. The time is in 24-hour format, and the date is encoded as year/month/day. The date must be specified, but you can omit the time or trailing parts of it, for example ``2002/11/27 1:50'' or ``2002/11/27''. @@ -1926,9 +1926,9 @@ simply not call \function{add\_constraints}, in which case the appropriate values will be chosen for you. The second function, \function{add\_ex\_constraints}, allows you to specify an -OID which has some meaning with regards to restricting the key to particular -usages. You can, if you wish, specify any OID you like, but there are a set of -standard ones which other applications will be able to understand. These are +OID that has some meaning with regards to restricting the key to particular +usages. You can, if you wish, specify any OID you like, but there is a set of +standard ones that other applications will be able to understand. These are the ones specified by the PKIX standard, and are named ``PKIX.ServerAuth'' (for TLS server authentication), ``PKIX.ClientAuth'' (for TLS client authentication), ``PKIX.CodeSigning'', ``PKIX.EmailProtection'' (most likely @@ -2102,7 +2102,7 @@ Stream ciphers implement the \type{SymmetricAlgorithm} interface. Some stream ciphers support random access to any point in their cipher stream. For such ciphers, calling \type{void} \function{seek}(\type{u32bit} -\arg{byte}) will change the cipher's state so that it as if the cipher had been +\arg{byte}) will change the cipher's state so that it is as if the cipher had been keyed as normal, then encrypted \arg{byte} -- 1 bytes of data (so the next byte in the cipher stream is byte number \arg{byte}). @@ -2140,14 +2140,14 @@ The second method of using final is to call it with no arguments at all, as shown in the second prototype. It will return the hash/mac value in a memory buffer, which will have size OUTPUT\_LENGTH. -There are also a pair of functions called \function{process}. They are +There is also a pair of functions called \function{process}. They are essentially a combination of a single \function{update}, and \function{final}. Both versions return the final value, rather than placing it an array. Calling \function{process} with a single byte value isn't available, mostly because it would rarely be useful. A MAC can be viewed (in most cases) as simply a keyed hash function, so classes -which are derived from \type{MessageAuthenticationCode} have \function{update} +that are derived from \type{MessageAuthenticationCode} have \function{update} and \function{final} classes just like a \type{HashFunction} (and like a \type{HashFunction}, after \function{final} is called, it can be used to make a new MAC right away; the key is kept around). @@ -2159,7 +2159,7 @@ A MAC has the \type{SymmetricAlgorithm} interface in addition to the \section{Random Number Generators} The random number generators provided in Botan are meant for creating keys, -IVs, padding, nonces, and anything else which requires 'random' data. It is +IVs, padding, nonces, and anything else that requires 'random' data. It is important to remember that the output of these classes will vary, even if they are supplied with exactly the same seed (\ie, two \type{Randpool} objects with similar initial states will not produce the same output, because the value of @@ -2257,14 +2257,14 @@ namespace. Note for writers of \type{EntropySource}s: it isn't necessary to use any kind of cryptographic hash on your output. The data produced by an EntropySource is only used by an application after it has been hashed by the -\type{RandomNumberGenerator} which asked for the entropy, thus any hashing +\type{RandomNumberGenerator} that asked for the entropy, thus any hashing you do will be wasteful of both CPU cycles and possibly entropy. \pagebreak \section{User Interfaces} Botan has recently changed some infrastructure to better accommodate more -complex user interfaces, in particular ones which are based on event +complex user interfaces, in particular ones that are based on event loops. Primary among these was the fact that when doing something like loading a PKCS \#8 encoded private key, a passphrase might be needed, but then again it might not (a PKCS \#8 key doesn't have to be encrypted). Asking for a @@ -2313,7 +2313,7 @@ exception will be thrown; your UI should assume this can happen, and provide appropriate error handling (such as putting up a dialog box informing the user of the situation, and canceling the operation in progress). -There is an example \type{UI} which uses GTK+ available on the web site. The +There is an example \type{UI} that uses GTK+ available on the web site. The \type{GTK\_UI} code is cleanly separated from the rest of the example, so if you happen to be using GTK+, you can copy (and/or adapt) that code for your application. If you write a \type{UI} object for another windowing system @@ -2324,7 +2324,7 @@ MIT/BSD), feel free to send in a copy. \pagebreak \section{Botan's Modules} -Botan comes with a variety of modules which can be compiled into the system. +Botan comes with a variety of modules that can be compiled into the system. These will not be available on all installations of the library, but you can check for their availability based on whether or not certain macros are defined. @@ -2375,7 +2375,7 @@ of this type around and run fast polls ever few minutes. \noindent \type{FTW\_EntropySource}: Walk through a filesystem (the root to start searching is passed as a string to the constructor), reading files. This tends -to only be useful on things like \filename{/proc} which have a great deal of +to only be useful on things like \filename{/proc} that have a great deal of variability over time, and even then there is only a small amount of entropy gathered: about 1 bit of entropy for every 16 bits of output (and many hundreds of bits are read in order to get that 16 bits). It is declared in @@ -2384,11 +2384,11 @@ use this as a last resort. I don't really trust it, and neither should you. \noindent \type{Win32\_CAPI\_EntropySource}: This routines gathers entropy from a Win32 -CAPI module. It takes an optional \type{std::string} which will specify what +CAPI module. It takes an optional \type{std::string} that will specify what type of CAPI provider to use. Generally the CAPI RNG is always the same -software-based PRNG, but there are a few which may use a hardware RNG. By +software-based PRNG, but there are a few that may use a hardware RNG. By default it will use the first provider listed in the option -``rng/ms\_capi\_prov\_type'' which is available on the machine (currently the +``rng/ms\_capi\_prov\_type'' that is available on the machine (currently the providers ``RSA\_FULL'', ``INTEL\_SEC'', ``FORTEZZA'', and ``RNG'' are recognized). @@ -2400,7 +2400,7 @@ APIs. \type{Pthread\_EntropySource}: Attempt to gather entropy based on jitter between a number of threads competing for a single mutex. This entropy source is \emph{very} slow, and highly questionable in terms of security. However, it -provides a worst-case fallback on systems which don't have Unix-like features, +provides a worst-case fallback on systems that don't have Unix-like features, but do support POSIX threads. This module is currently unavailable due to problems on some systems. @@ -2495,12 +2495,12 @@ up a file with that name and read from it. \subsubsection{Data Sinks} -A \type{DataSink} (in \filename{data\_snk.h}) is a \type{Filter} which takes +A \type{DataSink} (in \filename{data\_snk.h}) is a \type{Filter} that takes arbitrary amounts of input, and produces no output. Generally, this means it's doing something with the data outside the realm of what \type{Filter}/\type{Pipe} can handle, for example, writing it to a file (which is what the \type{DataSink\_Stream} does). There is no need for -\type{DataSink}s which write to a \type{std::string} or memory buffer, because +\type{DataSink}s that write to a \type{std::string} or memory buffer, because \type{Pipe} can handle that by itself. Here's a quick example of using a \type{DataSink}, which encrypts @@ -2643,7 +2643,7 @@ recommend for new applications. \subsubsection{OpenPGP S2K} -There are some oddities about OpenPGP's S2K algorithms which are documented +There are some oddities about OpenPGP's S2K algorithms that are documented here. For one thing, it uses the iteration count in a strange manner; instead of specifying how many times to iterate the hash, it tells how many \emph{bytes} should be hashed in total (including the salt). So the exact @@ -2697,7 +2697,7 @@ standard ones. \subsection{Threads and Mutexes} Botan includes a mutex system, which is used internally to lock some shared -data structures which must be kept shared for efficiency reasons (mostly, these +data structures that must be kept shared for efficiency reasons (mostly, these are in the allocation systems~--~handing out 1000 separate allocators hurts performance and makes caching memory blocks useless). This system is supported by the \texttt{mux\_pthr} module, implementing the \type{Mutex} interface for @@ -2715,7 +2715,7 @@ A major concern with mixing modern multiuser OSes and cryptographic code is that at any time the code (including secret keys) could be swapped to disk, where it can later be read by an attacker. Botan stores almost everything (and especially anything sensitive) in memory -buffers which a) clear out their contents when their destructors are +buffers that a) clear out their contents when their destructors are called, and b) have easy plugins for various memory locking functions, such as the \function{mlock}(2) call on many Unix systems. @@ -2816,7 +2816,7 @@ and \type{BigInt} \function{BigInt::decode}(\type{SecureVector<byte>}, \type{Encoding}) -\type{Encoding} is an enum which has values \type{Binary}, \type{Octal}, +\type{Encoding} is an enum that has values \type{Binary}, \type{Octal}, \type{Decimal}, and \type{Hexadecimal}. The parameter will default to \type{Binary}. These functions are static member functions, so they would be called like this: @@ -2945,7 +2945,7 @@ PKCS \#10} \noindent There is also support for the very general standards of \textbf{IEEE 1363-2000} and \textbf{1363a}. Most of the contents of such are included in the standards -mentioned above, in various forms (usually with extra restrictions which 1363 +mentioned above, in various forms (usually with extra restrictions that 1363 does not impose). \subsection{Algorithms Listing} @@ -2955,7 +2955,7 @@ nearly all cases, you never need to know the header file or type name to use them. However, you do need to know what string (or strings) are used to identify that algorithm. Generally, these names conform to those set out by SCAN (Standard Cryptographic Algorithm Naming), which -is a document which specifies how strings are mapped onto algorithm +is a document that specifies how strings are mapped onto algorithm objects, which is useful for a wide variety of crypto APIs (SCAN is oriented towards Java, but Botan and several other non-Java libraries also make at least some use of it). For full details, read the SCAN @@ -3008,7 +3008,7 @@ match that in SCAN, if it's defined there). Generally, cryptographic algorithms are well standardized, thus compatibility between implementations is relatively simple (of course, not all algorithms are supported by all implementations). But there are a few -algorithms which are poorly specified, and these should be avoided if you wish +algorithms that are poorly specified, and these should be avoided if you wish your data to be processed in the same way by another implementation (including future versions of Botan). @@ -3027,7 +3027,7 @@ algorithms, TripleDES, AES, HMAC, and SHA-256 all being good examples. Some of the algorithms implemented by Botan may be covered by patents in some locations. Algorithms known to have patent claims on them in the United States -and which are not available in a license-free/royalty-free manner include: +and that are not available in a license-free/royalty-free manner include: IDEA, MISTY1, RC5, RC6, and Nyberg-Rueppel. You must not assume that, just because an algorithm is not listed here, it is diff --git a/doc/credits.txt b/doc/credits.txt index fbc1fb796..ef2ee6bc1 100644 --- a/doc/credits.txt +++ b/doc/credits.txt @@ -11,6 +11,11 @@ S - meatspace location ---------- +N - Charles Brockman +W - http://www.securitygenetics.com/ +D - documentation editing +S - Oregon, USA + N: Martin Doering D: GF(p) arithmetic diff --git a/doc/examples/bench.cpp b/doc/examples/bench.cpp new file mode 100644 index 000000000..37ef1104d --- /dev/null +++ b/doc/examples/bench.cpp @@ -0,0 +1,98 @@ +#include <botan/benchmark.h> +#include <botan/init.h> +#include <botan/auto_rng.h> +#include <botan/libstate.h> + +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", + "AES-256", + "Blowfish", + "CAST-128", + "CAST-256", + "DES", + "DESX", + "TripleDES", + "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", + "Twofish", + "XTEA", + "Adler32", + "CRC32", + "FORK-256", + "GOST-34.11", + "HAS-160", + "HAS-V", + "MD2", + "MD4", + "MD5", + "RIPEMD-128", + "RIPEMD-160", + "SHA-160", + "SHA-256", + "SHA-384", + "SHA-512", + "Skein-512", + "Tiger", + "Whirlpool", + "CMAC(AES-128)", + "HMAC(SHA-1)", + "X9.19-MAC", + "", +}; + +int main() + { + LibraryInitializer init; + + u32bit milliseconds = 1000; + AutoSeeded_RNG rng; + Default_Benchmark_Timer timer; + + for(u32bit i = 0; algos[i] != ""; ++i) + { + std::string algo = algos[i]; + std::cout << algo << ' ' + << best_speed(algo, milliseconds, rng, timer) << "\n"; + } + } diff --git a/doc/examples/cryptobox.cpp b/doc/examples/cryptobox.cpp new file mode 100644 index 000000000..0a769b0cd --- /dev/null +++ b/doc/examples/cryptobox.cpp @@ -0,0 +1,50 @@ +/* +* Cryptobox example +*/ +#include <botan/botan.h> +#include <botan/cryptobox.h> +#include <fstream> +#include <iostream> +#include <vector> + +using namespace Botan; + +int main(int argc, char* argv[]) + { + LibraryInitializer init; + + AutoSeeded_RNG rng; + + if(argc != 3) + { + std::cout << "Usage: cryptobox pass filename\n"; + return 1; + } + + std::string pass = argv[1]; + std::string filename = argv[2]; + + std::ifstream input(filename.c_str()); + + std::vector<byte> file_contents; + while(input.good()) + { + byte filebuf[4096] = { 0 }; + input.read((char*)filebuf, sizeof(filebuf)); + size_t got = input.gcount(); + + file_contents.insert(file_contents.end(), filebuf, filebuf+got); + } + + std::string ciphertext = CryptoBox::encrypt(&file_contents[0], + file_contents.size(), + pass, rng); + + std::cout << ciphertext; + + /* + std::cout << CryptoBox::decrypt((const byte*)&ciphertext[0], + ciphertext.length(), + pass); + */ + } diff --git a/doc/examples/gen_certs.cpp b/doc/examples/gen_certs.cpp new file mode 100644 index 000000000..f635e1ccf --- /dev/null +++ b/doc/examples/gen_certs.cpp @@ -0,0 +1,124 @@ +/* +* Generate a root CA plus httpd, dovecot, and postfix certs/keys +* +*/ + +#include <botan/botan.h> +#include <botan/rsa.h> +#include <botan/util.h> +#include <botan/x509self.h> +#include <botan/x509_ca.h> + +using namespace Botan; + +#include <iostream> +#include <fstream> + +void fill_commoninfo(X509_Cert_Options& opts) + { + opts.country = "US"; + opts.organization = "randombit.net"; + opts.email = "[email protected]"; + opts.locality = "Vermont"; + } + +X509_Certificate make_ca_cert(RandomNumberGenerator& rng, + const Private_Key& priv_key, + const X509_Time& now, + const X509_Time& later) + { + X509_Cert_Options opts; + fill_commoninfo(opts); + opts.common_name = "randombit.net CA"; + opts.start = now; + opts.end = later; + opts.CA_key(); + + return X509::create_self_signed_cert(opts, priv_key, rng); + } + +PKCS10_Request make_server_cert_req(const Private_Key& key, + const std::string& hostname, + RandomNumberGenerator& rng) + { + X509_Cert_Options opts; + opts.common_name = hostname; + fill_commoninfo(opts); + + opts.add_ex_constraint("PKIX.ServerAuth"); + + return X509::create_cert_req(opts, key, rng); + } + +void save_pair(const std::string& name, + const std::string& password, + const X509_Certificate& cert, + const Private_Key& key, + RandomNumberGenerator& rng) + { + std::string cert_fsname = name + "_cert.pem"; + std::string key_fsname = name + "_key.pem"; + + std::ofstream cert_out(cert_fsname.c_str()); + cert_out << cert.PEM_encode() << "\n"; + cert_out.close(); + + std::ofstream key_out(key_fsname.c_str()); + if(password != "") + key_out << PKCS8::PEM_encode(key, rng, password); + else + key_out << PKCS8::PEM_encode(key); + key_out.close(); + } + +int main() + { + const u32bit seconds_in_a_year = 31556926; + + const u32bit current_time = system_time(); + + X509_Time now = X509_Time(current_time); + X509_Time later = X509_Time(current_time + 4*seconds_in_a_year); + + LibraryInitializer init; + + AutoSeeded_RNG rng; + + RSA_PrivateKey ca_key(rng, 2048); + + X509_Certificate ca_cert = make_ca_cert(rng, ca_key, now, later); + + const std::string ca_password = "sekrit"; + + save_pair("ca", ca_password, ca_cert, ca_key, rng); + + X509_CA ca(ca_cert, ca_key); + + RSA_PrivateKey httpd_key(rng, 1536); + X509_Certificate httpd_cert = ca.sign_request( + make_server_cert_req(httpd_key, "www.randombit.net", rng), + rng, now, later); + + save_pair("httpd", "", httpd_cert, httpd_key, rng); + + RSA_PrivateKey bugzilla_key(rng, 1536); + X509_Certificate bugzilla_cert = ca.sign_request( + make_server_cert_req(bugzilla_key, "bugs.randombit.net", rng), + rng, now, later); + + save_pair("bugzilla", "", bugzilla_cert, bugzilla_key, rng); + + RSA_PrivateKey postfix_key(rng, 1536); + X509_Certificate postfix_cert = ca.sign_request( + make_server_cert_req(postfix_key, "mail.randombit.net", rng), + rng, now, later); + + save_pair("postfix", "", postfix_cert, postfix_key, rng); + + RSA_PrivateKey dovecot_key(rng, 1536); + X509_Certificate dovecot_cert = ca.sign_request( + make_server_cert_req(dovecot_key, "imap.randombit.net", rng), + rng, now, later); + + save_pair("dovecot", "", dovecot_cert, dovecot_key, rng); + } diff --git a/doc/license.txt b/doc/license.txt index 4c3fc1999..9d1067cc1 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -1,3 +1,5 @@ +Botan (http://botan.randombit.net/) is distributed under these terms: + Copyright (C) 1999-2009 Jack Lloyd 2001 Peter J Jones 2004-2007 Justin Karneges @@ -12,10 +14,11 @@ Copyright (C) 1999-2009 Jack Lloyd 2007 Manuel Hartl 2007 Christoph Ludwig 2007 Patrick Sona +All rights reserved. -Redistribution and use in source and binary forms, for any use, with -or without modification, of Botan (http://botan.randombit.net/) is -permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. @@ -27,13 +30,11 @@ documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, -ARE DISCLAIMED. - -IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/doc/log.txt b/doc/log.txt index 831757d63..345e91d71 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,7 +1,29 @@ -* 1.8.5-rc1, 2009-07-20 +* 1.9.0-pre, 2009-??-?? + - 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 + +* 1.8.7-pre, 2009-??-?? + - Fix processing multiple messages in XTS mode + - Add --no-autoload option to configure.py, for minimized builds + +* 1.8.6, 2009-08-13 + - Add Cryptobox, a set of simple password-based encryption routines + - Only read world-readable files when walking /proc for entropy + - Fix building with TR1 disabled + - Fix x86 bswap support for Visual C++ + - Fixes for compilation under Sun C++ + - Add support for Dragonfly BSD (contributed by Patrick Georgi) + - Add support for the Open64 C++ compiler + - Build fixes for MIPS systems running Linux + - Minor changes to license, now equivalent to the FreeBSD/NetBSD license + +* 1.8.5, 2009-07-23 - Change configure.py to work on stock Python 2.4 - Avoid a crash in Skein_512::add_data processing a zero-length input + - Small build fixes for SPARC, ARM, and HP-PA processors - The test suite now returns an error code from main() if any tests failed * 1.8.4, 2009-07-12 diff --git a/configure.pl b/doc/scripts/configure.pl index 85b1508b8..6cf43e5e6 100755 --- a/configure.pl +++ b/doc/scripts/configure.pl @@ -13,11 +13,11 @@ use Sys::Hostname; my $MAJOR_VERSION = 1; my $MINOR_VERSION = 8; -my $PATCH_VERSION = 5; +my $PATCH_VERSION = 7; -my $VERSION_SUFFIX = '-rc1'; +my $VERSION_SUFFIX = '-pre'; -my $SO_PATCH_VERSION = 5; +my $SO_PATCH_VERSION = 7; my $VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION$VERSION_SUFFIX"; my $SO_VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$SO_PATCH_VERSION$VERSION_SUFFIX"; @@ -40,10 +40,6 @@ my $TRACING = 0; ################################################## my $config = {}; -print STDERR "* WARNING\n" . - "* $0 is deprecated; consider trying configure.py instead\n" . - "* If it works, great. If not, file a bug and continue using $0\n*\n"; - main(); exit; @@ -60,12 +56,18 @@ sub exec_uname { return ''; } +sub deprecation_warning { + warning("$0 is deprecated; migration to ./configure.py strongly recommended"); +} + ################################################## # Main Driver # ################################################## sub main { my $base_dir = where_am_i(); + deprecation_warning(); + $$config{'uname'} = exec_uname(); $$config{'base-dir'} = $base_dir; @@ -161,8 +163,7 @@ sub main { File::Spec->catdir($$config{'build_dir'}, 'include', 'botan'), 'mp_bits' => find_mp_bits($config), - 'mod_libs' => - [ using_libs($os, sort keys %{$$config{'modules'}}) ], + 'mod_libs' => [ using_libs($config) ], 'sources' => { }, 'includes' => { }, @@ -202,6 +203,8 @@ sub main { generate_makefile($config); copy_include_files($config); + + deprecation_warning(); } sub where_am_i { @@ -509,8 +512,6 @@ sub module_runs_on { sub scan_modules { my ($config) = @_; - my %dep_mods = (); - foreach my $mod (sort keys %MODULES) { my %modinfo = %{ $MODULES{$mod} }; @@ -519,9 +520,11 @@ sub scan_modules { next unless(module_runs_on($config, \%modinfo, $mod, 0)); if($modinfo{'load_on'} eq 'auto' or + $modinfo{'load_on'} eq 'always' or ($modinfo{'load_on'} eq 'asm_ok' and $$config{'asm_ok'})) { - $$config{'modules'}{$mod} = 1; + my %maybe_load = (); + my $all_deps_found = 1; LINE: foreach (@{$modinfo{'requires'}}) { for my $req_mod (split(/\|/, $_)) { @@ -530,18 +533,19 @@ sub scan_modules { next if(defined($$config{'modules'}{$req_mod}) && $$config{'modules'}{$req_mod} < 0); next unless(module_runs_on($config, $MODULES{$req_mod}, $req_mod, 0)); - $dep_mods{$req_mod} = 1; + $maybe_load{$req_mod} = 1; next LINE; } + $all_deps_found = 0; } - next; + if($all_deps_found) { + foreach my $depmod (keys %maybe_load) + { $$config{'modules'}{$depmod} = 1; } + $$config{'modules'}{$mod} = 1; + } } } - - foreach my $mod (sort keys %dep_mods) { - $$config{'modules'}{$mod} = 1; - } } sub print_enabled_modules { @@ -939,24 +943,30 @@ sub mach_opt { # # ################################################## sub using_libs { - my ($os,@using) = @_; + my ($config) = @_; + + my $os = $$config{'os'}; my %libs; - foreach my $mod (@using) { + foreach my $mod (sort keys %{$$config{'modules'}}) { + next if ${$$config{'modules'}}{$mod} < 0; + my %MOD_LIBS = %{ $MODULES{$mod}{'libs'} }; - foreach my $mod_os (keys %MOD_LIBS) { + + foreach my $mod_os (keys %MOD_LIBS) + { next if($mod_os =~ /^all!$os$/); next if($mod_os =~ /^all!$os,/); - next if($mod_os =~ /^all!.*,${os}$/); + #next if($mod_os =~ /^all!.*,${os}$/); next if($mod_os =~ /^all!.*,$os,.*/); next unless($mod_os eq $os or ($mod_os =~ /^all.*/)); my @liblist = split(/,/, $MOD_LIBS{$mod_os}); foreach my $lib (@liblist) { $libs{$lib} = 1; } - } } + } return sort keys %libs; - } +} sub libs { my ($prefix,$suffix,@libs) = @_; @@ -1270,6 +1280,7 @@ sub load_modules { if($arch ne $submodel) { $submodel = uc $submodel; $submodel =~ tr/-/_/; + $submodel =~ tr/.//; push @macro_list, "#define BOTAN_TARGET_CPU_IS_$submodel"; } diff --git a/doc/scripts/dist.sh b/doc/scripts/dist.sh index d66066173..0062d43bf 100755 --- a/doc/scripts/dist.sh +++ b/doc/scripts/dist.sh @@ -5,8 +5,8 @@ SELECTOR=h:net.randombit.botan KEY_ID=EFBADFBC -MTN_DB=~/var/mtn/botan.mtn -WEB_DIR=~/var/www +MTN_DB=/storage/mtn/botan.mtn +WEB_DIR=~/projects/www DIST_DIR=~/Botan-dist # You shouldn't have to change anything after this @@ -15,7 +15,7 @@ cd $DIST_DIR mtn -d $MTN_DB checkout -r $SELECTOR Botan -VERSION=$(Botan/configure.pl --version | sed 's/Botan //') +VERSION=$(Botan/configure.py --version) mv Botan Botan-$VERSION diff --git a/readme.txt b/readme.txt index 8b9c96531..4936116f0 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -Botan 1.8.5-rc1 2009-07-20 +Botan 1.9.0-pre 2009-??-?? Botan is a C++ class library for performing a wide variety of cryptographic operations. diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index 71bd26827..e891dc5cd 100644 --- a/src/algo_factory/algo_factory.cpp +++ b/src/algo_factory/algo_factory.cpp @@ -1,6 +1,6 @@ /* -Algorithm Factory -(C) 2008 Jack Lloyd +* Algorithm Factory +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/alloc/alloc_mmap/info.txt b/src/alloc/alloc_mmap/info.txt index d8c766d55..65d9b2977 100644 --- a/src/alloc/alloc_mmap/info.txt +++ b/src/alloc/alloc_mmap/info.txt @@ -13,6 +13,7 @@ mmap_mem.h <os> linux freebsd +dragonfly openbsd netbsd solaris diff --git a/src/aont/info.txt b/src/aont/info.txt new file mode 100644 index 000000000..a0387f358 --- /dev/null +++ b/src/aont/info.txt @@ -0,0 +1,17 @@ +realname "All or Nothing Transforms" + +define PACKAGE_TRANSFORM + +load_on auto + +<add> +package.cpp +package.h +</add> + +<requires> +block +ctr +rng +filters +</requires> diff --git a/src/aont/package.cpp b/src/aont/package.cpp new file mode 100644 index 000000000..6c6b56865 --- /dev/null +++ b/src/aont/package.cpp @@ -0,0 +1,128 @@ +/* +* Rivest's Package Tranform +* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/package.h> +#include <botan/pipe.h> +#include <botan/ctr.h> +#include <botan/loadstor.h> +#include <botan/xor_buf.h> + +namespace Botan { + +namespace AllOrNothingTransform { + +void package(RandomNumberGenerator& rng, + BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]) + { + if(!cipher->valid_keylength(cipher->BLOCK_SIZE)) + throw Invalid_Argument("AONT::package: Invalid cipher"); + + // The all-zero string which is used both as the CTR IV and as K0 + const std::string all_zeros(cipher->BLOCK_SIZE*2, '0'); + + SymmetricKey package_key(rng, cipher->BLOCK_SIZE); + + // takes ownership of cipher object + Keyed_Filter* ctr_mode = new CTR_BE(cipher, + package_key, + InitializationVector(all_zeros)); + + Pipe pipe(ctr_mode); + + pipe.process_msg(input, input_len); + pipe.read(output, pipe.remaining()); + + // Set K0 (the all zero key) + cipher->set_key(SymmetricKey(all_zeros)); + + SecureVector<byte> buf(cipher->BLOCK_SIZE); + + const u32bit blocks = + (input_len + cipher->BLOCK_SIZE - 1) / cipher->BLOCK_SIZE; + + byte* final_block = output + input_len; + clear_mem(final_block, cipher->BLOCK_SIZE); + + // XOR the hash blocks into the final block + for(u32bit i = 0; i != blocks; ++i) + { + u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE, + input_len - cipher->BLOCK_SIZE * i); + + buf.clear(); + copy_mem(&buf[0], output + cipher->BLOCK_SIZE * i, left); + + for(u32bit j = 0; j != 4; ++j) + buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i); + + cipher->encrypt(buf); + + xor_buf(final_block, buf, cipher->BLOCK_SIZE); + } + + // XOR the random package key into the final block + xor_buf(final_block, package_key.begin(), cipher->BLOCK_SIZE); + } + +void unpackage(BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]) + { + if(!cipher->valid_keylength(cipher->BLOCK_SIZE)) + throw Invalid_Argument("AONT::unpackage: Invalid cipher"); + + if(input_len < cipher->BLOCK_SIZE) + throw Invalid_Argument("AONT::unpackage: Input too short"); + + // The all-zero string which is used both as the CTR IV and as K0 + const std::string all_zeros(cipher->BLOCK_SIZE*2, '0'); + + cipher->set_key(SymmetricKey(all_zeros)); + + SecureVector<byte> package_key(cipher->BLOCK_SIZE); + SecureVector<byte> buf(cipher->BLOCK_SIZE); + + // Copy the package key (masked with the block hashes) + copy_mem(&package_key[0], + input + (input_len - cipher->BLOCK_SIZE), + cipher->BLOCK_SIZE); + + const u32bit blocks = ((input_len - 1) / cipher->BLOCK_SIZE); + + // XOR the blocks into the package key bits + for(u32bit i = 0; i != blocks; ++i) + { + u32bit left = std::min<u32bit>(cipher->BLOCK_SIZE, + input_len - cipher->BLOCK_SIZE * (i+1)); + + buf.clear(); + copy_mem(&buf[0], input + cipher->BLOCK_SIZE * i, left); + + for(u32bit j = 0; j != 4; ++j) + buf[cipher->BLOCK_SIZE - 1 - j] ^= get_byte(3-j, i); + + cipher->encrypt(buf); + + xor_buf(&package_key[0], buf, cipher->BLOCK_SIZE); + } + + // takes ownership of cipher object + Pipe pipe(new CTR_BE(cipher, + SymmetricKey(package_key), + InitializationVector(all_zeros))); + + pipe.process_msg(input, input_len - cipher->BLOCK_SIZE); + + pipe.read(output, pipe.remaining()); + } + +} + +} diff --git a/src/aont/package.h b/src/aont/package.h new file mode 100644 index 000000000..35d2a23fc --- /dev/null +++ b/src/aont/package.h @@ -0,0 +1,45 @@ +/* +* Rivest's Package Tranform +* +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/block_cipher.h> +#include <botan/rng.h> + +namespace Botan { + +namespace AllOrNothingTransform { + +/** +* Rivest's Package Tranform +* @arg rng the random number generator to use +* @arg cipher the block cipher to use +* @arg input the input data buffer +* @arg input_len the length of the input data in bytes +* @arg output the output data buffer (must be at least +* input_len + cipher->BLOCK_SIZE bytes long) +*/ +void package(RandomNumberGenerator& rng, + BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]); + +/** +* Rivest's Package Tranform (Inversion) +* @arg rng the random number generator to use +* @arg cipher the block cipher to use +* @arg input the input data buffer +* @arg input_len the length of the input data in bytes +* @arg output the output data buffer (must be at least +* input_len - cipher->BLOCK_SIZE bytes long) +*/ +void unpackage(BlockCipher* cipher, + const byte input[], u32bit input_len, + byte output[]); + +} + +} diff --git a/src/benchmark/benchmark.cpp b/src/benchmark/benchmark.cpp index d30e831b9..3bbc1f883 100644 --- a/src/benchmark/benchmark.cpp +++ b/src/benchmark/benchmark.cpp @@ -57,8 +57,7 @@ bench_block_cipher(BlockCipher* block_cipher, while(nanoseconds_used < nanoseconds_max) { - for(u32bit i = 0; i != in_blocks; ++i) - block_cipher->encrypt(buf + block_cipher->BLOCK_SIZE * i); + block_cipher->encrypt_n(buf, buf, in_blocks); ++reps; nanoseconds_used = timer.clock() - start; @@ -140,7 +139,7 @@ algorithm_benchmark(const std::string& name, { const std::string provider = providers[i]; - std::pair<u64bit, u64bit> results = std::make_pair(0, 0); + std::pair<u64bit, u64bit> results(0, 0); if(const BlockCipher* proto = af.prototype_block_cipher(name, provider)) diff --git a/src/block/aes/aes.cpp b/src/block/aes/aes.cpp index 9072b507b..34698ae7f 100644 --- a/src/block/aes/aes.cpp +++ b/src/block/aes/aes.cpp @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,163 +13,175 @@ namespace Botan { /** * AES Encryption */ -void AES::enc(const byte in[], byte out[]) const +void AES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TE0 = TE; const u32bit* TE1 = TE + 256; const u32bit* TE2 = TE + 512; const u32bit* TE3 = TE + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; - u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2]; - u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3]; - - u32bit B0, B1, B2, B3; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4]; - B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ - TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5]; - B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ - TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6]; - B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ - TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = EK[4*j]; - const u32bit K1 = EK[4*j+1]; - const u32bit K2 = EK[4*j+2]; - const u32bit K3 = EK[4*j+3]; - - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; - T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ - TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; - T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ - TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; - T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ - TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; - - const u32bit K4 = EK[4*(j+1)+0]; - const u32bit K5 = EK[4*(j+1)+1]; - const u32bit K6 = EK[4*(j+1)+2]; - const u32bit K7 = EK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ EK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ EK[1]; + u32bit T2 = load_be<u32bit>(in, 2) ^ EK[2]; + u32bit T3 = load_be<u32bit>(in, 3) ^ EK[3]; + u32bit B0, B1, B2, B3; B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4; + TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4]; B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ - TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5; + TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ EK[5]; B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ - TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6; + TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ EK[6]; B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ - TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7; - } + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ EK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = EK[4*j]; + const u32bit K1 = EK[4*j+1]; + const u32bit K2 = EK[4*j+2]; + const u32bit K3 = EK[4*j+3]; + + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(3, B3)] ^ K0; + T1 = TE0[get_byte(0, B1)] ^ TE1[get_byte(1, B2)] ^ + TE2[get_byte(2, B3)] ^ TE3[get_byte(3, B0)] ^ K1; + T2 = TE0[get_byte(0, B2)] ^ TE1[get_byte(1, B3)] ^ + TE2[get_byte(2, B0)] ^ TE3[get_byte(3, B1)] ^ K2; + T3 = TE0[get_byte(0, B3)] ^ TE1[get_byte(1, B0)] ^ + TE2[get_byte(2, B1)] ^ TE3[get_byte(3, B2)] ^ K3; + + const u32bit K4 = EK[4*(j+1)+0]; + const u32bit K5 = EK[4*(j+1)+1]; + const u32bit K6 = EK[4*(j+1)+2]; + const u32bit K7 = EK[4*(j+1)+3]; - /* - Joseph Bonneau and Ilya Mironov's paper - <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf"> - Cache-Collision Timing Attacks Against AES</a> describes an attack - that can recover AES keys with as few as 2<sup>13</sup> samples. - - """In addition to OpenSSL v. 0.9.8.(a), which was used in our - experiments, the AES implementations of Crypto++ 5.2.1 and - LibTomCrypt 1.09 use the original Rijndael C implementation with - very few changes and are highly vulnerable. The AES implementations - in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but - use a smaller byte-wide final table which lessens the effectiveness - of the attacks.""" - */ - out[ 0] = SE[get_byte(0, B0)] ^ ME[0]; - out[ 1] = SE[get_byte(1, B1)] ^ ME[1]; - out[ 2] = SE[get_byte(2, B2)] ^ ME[2]; - out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; - out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; - out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; - out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; - out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; - out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; - out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; - out[10] = SE[get_byte(2, B0)] ^ ME[10]; - out[11] = SE[get_byte(3, B1)] ^ ME[11]; - out[12] = SE[get_byte(0, B3)] ^ ME[12]; - out[13] = SE[get_byte(1, B0)] ^ ME[13]; - out[14] = SE[get_byte(2, B1)] ^ ME[14]; - out[15] = SE[get_byte(3, B2)] ^ ME[15]; + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(3, T3)] ^ K4; + B1 = TE0[get_byte(0, T1)] ^ TE1[get_byte(1, T2)] ^ + TE2[get_byte(2, T3)] ^ TE3[get_byte(3, T0)] ^ K5; + B2 = TE0[get_byte(0, T2)] ^ TE1[get_byte(1, T3)] ^ + TE2[get_byte(2, T0)] ^ TE3[get_byte(3, T1)] ^ K6; + B3 = TE0[get_byte(0, T3)] ^ TE1[get_byte(1, T0)] ^ + TE2[get_byte(2, T1)] ^ TE3[get_byte(3, T2)] ^ K7; + } + + /* + Joseph Bonneau and Ilya Mironov's paper + <a href = "http://icme2007.org/users/mironov/papers/aes-timing.pdf"> + Cache-Collision Timing Attacks Against AES</a> describes an attack + that can recover AES keys with as few as 2<sup>13</sup> samples. + + """In addition to OpenSSL v. 0.9.8.(a), which was used in our + experiments, the AES implementations of Crypto++ 5.2.1 and + LibTomCrypt 1.09 use the original Rijndael C implementation with + very few changes and are highly vulnerable. The AES implementations + in libgcrypt v. 1.2.2 and Botan v. 1.4.2 are also vulnerable, but + use a smaller byte-wide final table which lessens the effectiveness + of the attacks.""" + */ + out[ 0] = SE[get_byte(0, B0)] ^ ME[0]; + out[ 1] = SE[get_byte(1, B1)] ^ ME[1]; + out[ 2] = SE[get_byte(2, B2)] ^ ME[2]; + out[ 3] = SE[get_byte(3, B3)] ^ ME[3]; + out[ 4] = SE[get_byte(0, B1)] ^ ME[4]; + out[ 5] = SE[get_byte(1, B2)] ^ ME[5]; + out[ 6] = SE[get_byte(2, B3)] ^ ME[6]; + out[ 7] = SE[get_byte(3, B0)] ^ ME[7]; + out[ 8] = SE[get_byte(0, B2)] ^ ME[8]; + out[ 9] = SE[get_byte(1, B3)] ^ ME[9]; + out[10] = SE[get_byte(2, B0)] ^ ME[10]; + out[11] = SE[get_byte(3, B1)] ^ ME[11]; + out[12] = SE[get_byte(0, B3)] ^ ME[12]; + out[13] = SE[get_byte(1, B0)] ^ ME[13]; + out[14] = SE[get_byte(2, B1)] ^ ME[14]; + out[15] = SE[get_byte(3, B2)] ^ ME[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** * AES Decryption */ -void AES::dec(const byte in[], byte out[]) const +void AES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* TD0 = TD; const u32bit* TD1 = TD + 256; const u32bit* TD2 = TD + 512; const u32bit* TD3 = TD + 768; - u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; - u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; - u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2]; - u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3]; - - u32bit B0, B1, B2, B3; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4]; - B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ - TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5]; - B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6]; - B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ - TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; - - for(u32bit j = 2; j != ROUNDS; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u32bit K0 = DK[4*j+0]; - const u32bit K1 = DK[4*j+1]; - const u32bit K2 = DK[4*j+2]; - const u32bit K3 = DK[4*j+3]; - - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; - T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ - TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; - T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; - T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ - TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; - - const u32bit K4 = DK[4*(j+1)+0]; - const u32bit K5 = DK[4*(j+1)+1]; - const u32bit K6 = DK[4*(j+1)+2]; - const u32bit K7 = DK[4*(j+1)+3]; + u32bit T0 = load_be<u32bit>(in, 0) ^ DK[0]; + u32bit T1 = load_be<u32bit>(in, 1) ^ DK[1]; + u32bit T2 = load_be<u32bit>(in, 2) ^ DK[2]; + u32bit T3 = load_be<u32bit>(in, 3) ^ DK[3]; + u32bit B0, B1, B2, B3; B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4; + TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ DK[4]; B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ - TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5; + TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ DK[5]; B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6; + TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ DK[6]; B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ - TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7; - } + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ DK[7]; + + for(u32bit j = 2; j != ROUNDS; j += 2) + { + const u32bit K0 = DK[4*j+0]; + const u32bit K1 = DK[4*j+1]; + const u32bit K2 = DK[4*j+2]; + const u32bit K3 = DK[4*j+3]; + + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(1, B3)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(3, B1)] ^ K0; + T1 = TD0[get_byte(0, B1)] ^ TD1[get_byte(1, B0)] ^ + TD2[get_byte(2, B3)] ^ TD3[get_byte(3, B2)] ^ K1; + T2 = TD0[get_byte(0, B2)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(2, B0)] ^ TD3[get_byte(3, B3)] ^ K2; + T3 = TD0[get_byte(0, B3)] ^ TD1[get_byte(1, B2)] ^ + TD2[get_byte(2, B1)] ^ TD3[get_byte(3, B0)] ^ K3; + + const u32bit K4 = DK[4*(j+1)+0]; + const u32bit K5 = DK[4*(j+1)+1]; + const u32bit K6 = DK[4*(j+1)+2]; + const u32bit K7 = DK[4*(j+1)+3]; - out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; - out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; - out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; - out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; - out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; - out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; - out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; - out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; - out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; - out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; - out[10] = SD[get_byte(2, B0)] ^ MD[10]; - out[11] = SD[get_byte(3, B3)] ^ MD[11]; - out[12] = SD[get_byte(0, B3)] ^ MD[12]; - out[13] = SD[get_byte(1, B2)] ^ MD[13]; - out[14] = SD[get_byte(2, B1)] ^ MD[14]; - out[15] = SD[get_byte(3, B0)] ^ MD[15]; + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(1, T3)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(3, T1)] ^ K4; + B1 = TD0[get_byte(0, T1)] ^ TD1[get_byte(1, T0)] ^ + TD2[get_byte(2, T3)] ^ TD3[get_byte(3, T2)] ^ K5; + B2 = TD0[get_byte(0, T2)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(2, T0)] ^ TD3[get_byte(3, T3)] ^ K6; + B3 = TD0[get_byte(0, T3)] ^ TD1[get_byte(1, T2)] ^ + TD2[get_byte(2, T1)] ^ TD3[get_byte(3, T0)] ^ K7; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[0]; + out[ 1] = SD[get_byte(1, B3)] ^ MD[1]; + out[ 2] = SD[get_byte(2, B2)] ^ MD[2]; + out[ 3] = SD[get_byte(3, B1)] ^ MD[3]; + out[ 4] = SD[get_byte(0, B1)] ^ MD[4]; + out[ 5] = SD[get_byte(1, B0)] ^ MD[5]; + out[ 6] = SD[get_byte(2, B3)] ^ MD[6]; + out[ 7] = SD[get_byte(3, B2)] ^ MD[7]; + out[ 8] = SD[get_byte(0, B2)] ^ MD[8]; + out[ 9] = SD[get_byte(1, B1)] ^ MD[9]; + out[10] = SD[get_byte(2, B0)] ^ MD[10]; + out[11] = SD[get_byte(3, B3)] ^ MD[11]; + out[12] = SD[get_byte(0, B3)] ^ MD[12]; + out[13] = SD[get_byte(1, B2)] ^ MD[13]; + out[14] = SD[get_byte(2, B1)] ^ MD[14]; + out[15] = SD[get_byte(3, B0)] ^ MD[15]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /** diff --git a/src/block/aes/aes.h b/src/block/aes/aes.h index 05e2e3123..768bb09e7 100644 --- a/src/block/aes/aes.h +++ b/src/block/aes/aes.h @@ -1,6 +1,6 @@ /** * AES -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,14 +18,16 @@ namespace Botan { class BOTAN_DLL AES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "AES"; } BlockCipher* clone() const { return new AES; } + AES() : BlockCipher(16, 16, 32, 8) { ROUNDS = 14; } AES(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static u32bit S(u32bit); diff --git a/src/block/block_cipher.h b/src/block/block_cipher.h index 01c45af04..a27609171 100644 --- a/src/block/block_cipher.h +++ b/src/block/block_cipher.h @@ -1,6 +1,6 @@ /** * Block Cipher Base Class -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -45,7 +45,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the encrypted block. * Must be of length BLOCK_SIZE. */ - void encrypt(const byte in[], byte out[]) const { enc(in, out); } + void encrypt(const byte in[], byte out[]) const + { encrypt_n(in, out, 1); } /** * Decrypt a block. @@ -54,7 +55,8 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param out The byte array designated to hold the decrypted block. * Must be of length BLOCK_SIZE. */ - void decrypt(const byte in[], byte out[]) const { dec(in, out); } + void decrypt(const byte in[], byte out[]) const + { decrypt_n(in, out, 1); } /** * Encrypt a block. @@ -62,7 +64,7 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void encrypt(byte block[]) const { enc(block, block); } + void encrypt(byte block[]) const { encrypt_n(block, block, 1); } /** * Decrypt a block. @@ -70,7 +72,12 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * Must be of length BLOCK_SIZE. Will hold the result when the function * has finished. */ - void decrypt(byte block[]) const { dec(block, block); } + void decrypt(byte block[]) const { decrypt_n(block, block, 1); } + + virtual void encrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; + virtual void decrypt_n(const byte in[], byte out[], + u32bit blocks) const = 0; /** * Get a new object representing the same algorithm as *this @@ -90,9 +97,6 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm BLOCK_SIZE(block_size) {} virtual ~BlockCipher() {} - private: - virtual void enc(const byte[], byte[]) const = 0; - virtual void dec(const byte[], byte[]) const = 0; }; } diff --git a/src/block/blowfish/blowfish.cpp b/src/block/blowfish/blowfish.cpp index b0599d6c5..312603c3a 100644 --- a/src/block/blowfish/blowfish.cpp +++ b/src/block/blowfish/blowfish.cpp @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,59 +13,71 @@ namespace Botan { /* * Blowfish Encryption */ -void Blowfish::enc(const byte in[], byte out[]) const +void Blowfish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j+1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 0; j != 16; j += 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[16]; R ^= P[17]; + R ^= P[j+1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[16]; R ^= P[17]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Blowfish Decryption */ -void Blowfish::dec(const byte in[], byte out[]) const +void Blowfish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { const u32bit* S1 = S + 0; const u32bit* S2 = S + 256; const u32bit* S3 = S + 512; const u32bit* S4 = S + 768; - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - for(u32bit j = 17; j != 1; j -= 2) + for(u32bit i = 0; i != blocks; ++i) { - L ^= P[j]; - R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ - S3[get_byte(2, L)]) + S4[get_byte(3, L)]; + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); - R ^= P[j-1]; - L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ - S3[get_byte(2, R)]) + S4[get_byte(3, R)]; - } + for(u32bit j = 17; j != 1; j -= 2) + { + L ^= P[j]; + R ^= ((S1[get_byte(0, L)] + S2[get_byte(1, L)]) ^ + S3[get_byte(2, L)]) + S4[get_byte(3, L)]; - L ^= P[1]; R ^= P[0]; + R ^= P[j-1]; + L ^= ((S1[get_byte(0, R)] + S2[get_byte(1, R)]) ^ + S3[get_byte(2, R)]) + S4[get_byte(3, R)]; + } + + L ^= P[1]; R ^= P[0]; - store_be(out, R, L); + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/blowfish/blowfish.h b/src/block/blowfish/blowfish.h index f0f26418d..345c1ce49 100644 --- a/src/block/blowfish/blowfish.h +++ b/src/block/blowfish/blowfish.h @@ -1,6 +1,6 @@ /* * Blowfish -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Blowfish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Blowfish"; } BlockCipher* clone() const { return new Blowfish; } + Blowfish() : BlockCipher(8, 1, 56) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void generate_sbox(u32bit[], u32bit, u32bit&, u32bit&) const; diff --git a/src/block/cast/cast128.cpp b/src/block/cast/cast128.cpp index 046638ab9..887dcf994 100644 --- a/src/block/cast/cast128.cpp +++ b/src/block/cast/cast128.cpp @@ -48,57 +48,69 @@ inline void R3(u32bit& L, u32bit R, u32bit MK, u32bit RK) /* * CAST-128 Encryption */ -void CAST_128::enc(const byte in[], byte out[]) const +void CAST_128::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[ 0], RK[ 0]); - R2(R, L, MK[ 1], RK[ 1]); - R3(L, R, MK[ 2], RK[ 2]); - R1(R, L, MK[ 3], RK[ 3]); - R2(L, R, MK[ 4], RK[ 4]); - R3(R, L, MK[ 5], RK[ 5]); - R1(L, R, MK[ 6], RK[ 6]); - R2(R, L, MK[ 7], RK[ 7]); - R3(L, R, MK[ 8], RK[ 8]); - R1(R, L, MK[ 9], RK[ 9]); - R2(L, R, MK[10], RK[10]); - R3(R, L, MK[11], RK[11]); - R1(L, R, MK[12], RK[12]); - R2(R, L, MK[13], RK[13]); - R3(L, R, MK[14], RK[14]); - R1(R, L, MK[15], RK[15]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[ 0], RK[ 0]); + R2(R, L, MK[ 1], RK[ 1]); + R3(L, R, MK[ 2], RK[ 2]); + R1(R, L, MK[ 3], RK[ 3]); + R2(L, R, MK[ 4], RK[ 4]); + R3(R, L, MK[ 5], RK[ 5]); + R1(L, R, MK[ 6], RK[ 6]); + R2(R, L, MK[ 7], RK[ 7]); + R3(L, R, MK[ 8], RK[ 8]); + R1(R, L, MK[ 9], RK[ 9]); + R2(L, R, MK[10], RK[10]); + R3(R, L, MK[11], RK[11]); + R1(L, R, MK[12], RK[12]); + R2(R, L, MK[13], RK[13]); + R3(L, R, MK[14], RK[14]); + R1(R, L, MK[15], RK[15]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-128 Decryption */ -void CAST_128::dec(const byte in[], byte out[]) const +void CAST_128::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0); - u32bit R = load_be<u32bit>(in, 1); - - R1(L, R, MK[15], RK[15]); - R3(R, L, MK[14], RK[14]); - R2(L, R, MK[13], RK[13]); - R1(R, L, MK[12], RK[12]); - R3(L, R, MK[11], RK[11]); - R2(R, L, MK[10], RK[10]); - R1(L, R, MK[ 9], RK[ 9]); - R3(R, L, MK[ 8], RK[ 8]); - R2(L, R, MK[ 7], RK[ 7]); - R1(R, L, MK[ 6], RK[ 6]); - R3(L, R, MK[ 5], RK[ 5]); - R2(R, L, MK[ 4], RK[ 4]); - R1(L, R, MK[ 3], RK[ 3]); - R3(R, L, MK[ 2], RK[ 2]); - R2(L, R, MK[ 1], RK[ 1]); - R1(R, L, MK[ 0], RK[ 0]); - - store_be(out, R, L); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit L = load_be<u32bit>(in, 0); + u32bit R = load_be<u32bit>(in, 1); + + R1(L, R, MK[15], RK[15]); + R3(R, L, MK[14], RK[14]); + R2(L, R, MK[13], RK[13]); + R1(R, L, MK[12], RK[12]); + R3(L, R, MK[11], RK[11]); + R2(R, L, MK[10], RK[10]); + R1(L, R, MK[ 9], RK[ 9]); + R3(R, L, MK[ 8], RK[ 8]); + R2(L, R, MK[ 7], RK[ 7]); + R1(R, L, MK[ 6], RK[ 6]); + R3(L, R, MK[ 5], RK[ 5]); + R2(R, L, MK[ 4], RK[ 4]); + R1(L, R, MK[ 3], RK[ 3]); + R3(R, L, MK[ 2], RK[ 2]); + R2(L, R, MK[ 1], RK[ 1]); + R1(R, L, MK[ 0], RK[ 0]); + + store_be(out, R, L); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast128.h b/src/block/cast/cast128.h index 680481482..864a4e47e 100644 --- a/src/block/cast/cast128.h +++ b/src/block/cast/cast128.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_128 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-128"; } BlockCipher* clone() const { return new CAST_128; } + CAST_128() : BlockCipher(8, 11, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void key_schedule(u32bit[16], u32bit[4]); diff --git a/src/block/cast/cast256.cpp b/src/block/cast/cast256.cpp index 22ff876fa..7a4a4e805 100644 --- a/src/block/cast/cast256.cpp +++ b/src/block/cast/cast256.cpp @@ -48,77 +48,89 @@ void round3(u32bit& out, u32bit in, u32bit mask, u32bit rot) /* * CAST-256 Encryption */ -void CAST_256::enc(const byte in[], byte out[]) const +void CAST_256::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); - round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); - round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); - round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); - round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); - round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); - round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); - round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); - round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); - round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); - round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); - round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); - round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); - round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); - round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); - round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); - round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); - round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); - round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); - round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); - round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); - round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); - round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); - round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[ 0], RK[ 0]); round2(B, C, MK[ 1], RK[ 1]); + round3(A, B, MK[ 2], RK[ 2]); round1(D, A, MK[ 3], RK[ 3]); + round1(C, D, MK[ 4], RK[ 4]); round2(B, C, MK[ 5], RK[ 5]); + round3(A, B, MK[ 6], RK[ 6]); round1(D, A, MK[ 7], RK[ 7]); + round1(C, D, MK[ 8], RK[ 8]); round2(B, C, MK[ 9], RK[ 9]); + round3(A, B, MK[10], RK[10]); round1(D, A, MK[11], RK[11]); + round1(C, D, MK[12], RK[12]); round2(B, C, MK[13], RK[13]); + round3(A, B, MK[14], RK[14]); round1(D, A, MK[15], RK[15]); + round1(C, D, MK[16], RK[16]); round2(B, C, MK[17], RK[17]); + round3(A, B, MK[18], RK[18]); round1(D, A, MK[19], RK[19]); + round1(C, D, MK[20], RK[20]); round2(B, C, MK[21], RK[21]); + round3(A, B, MK[22], RK[22]); round1(D, A, MK[23], RK[23]); + round1(D, A, MK[27], RK[27]); round3(A, B, MK[26], RK[26]); + round2(B, C, MK[25], RK[25]); round1(C, D, MK[24], RK[24]); + round1(D, A, MK[31], RK[31]); round3(A, B, MK[30], RK[30]); + round2(B, C, MK[29], RK[29]); round1(C, D, MK[28], RK[28]); + round1(D, A, MK[35], RK[35]); round3(A, B, MK[34], RK[34]); + round2(B, C, MK[33], RK[33]); round1(C, D, MK[32], RK[32]); + round1(D, A, MK[39], RK[39]); round3(A, B, MK[38], RK[38]); + round2(B, C, MK[37], RK[37]); round1(C, D, MK[36], RK[36]); + round1(D, A, MK[43], RK[43]); round3(A, B, MK[42], RK[42]); + round2(B, C, MK[41], RK[41]); round1(C, D, MK[40], RK[40]); + round1(D, A, MK[47], RK[47]); round3(A, B, MK[46], RK[46]); + round2(B, C, MK[45], RK[45]); round1(C, D, MK[44], RK[44]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * CAST-256 Decryption */ -void CAST_256::dec(const byte in[], byte out[]) const +void CAST_256::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_be<u32bit>(in, 0); - u32bit B = load_be<u32bit>(in, 1); - u32bit C = load_be<u32bit>(in, 2); - u32bit D = load_be<u32bit>(in, 3); - - round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); - round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); - round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); - round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); - round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); - round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); - round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); - round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); - round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); - round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); - round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); - round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); - round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); - round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); - round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); - round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); - round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); - round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); - round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); - round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); - round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); - round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); - round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); - round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); - - store_be(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_be<u32bit>(in, 0); + u32bit B = load_be<u32bit>(in, 1); + u32bit C = load_be<u32bit>(in, 2); + u32bit D = load_be<u32bit>(in, 3); + + round1(C, D, MK[44], RK[44]); round2(B, C, MK[45], RK[45]); + round3(A, B, MK[46], RK[46]); round1(D, A, MK[47], RK[47]); + round1(C, D, MK[40], RK[40]); round2(B, C, MK[41], RK[41]); + round3(A, B, MK[42], RK[42]); round1(D, A, MK[43], RK[43]); + round1(C, D, MK[36], RK[36]); round2(B, C, MK[37], RK[37]); + round3(A, B, MK[38], RK[38]); round1(D, A, MK[39], RK[39]); + round1(C, D, MK[32], RK[32]); round2(B, C, MK[33], RK[33]); + round3(A, B, MK[34], RK[34]); round1(D, A, MK[35], RK[35]); + round1(C, D, MK[28], RK[28]); round2(B, C, MK[29], RK[29]); + round3(A, B, MK[30], RK[30]); round1(D, A, MK[31], RK[31]); + round1(C, D, MK[24], RK[24]); round2(B, C, MK[25], RK[25]); + round3(A, B, MK[26], RK[26]); round1(D, A, MK[27], RK[27]); + round1(D, A, MK[23], RK[23]); round3(A, B, MK[22], RK[22]); + round2(B, C, MK[21], RK[21]); round1(C, D, MK[20], RK[20]); + round1(D, A, MK[19], RK[19]); round3(A, B, MK[18], RK[18]); + round2(B, C, MK[17], RK[17]); round1(C, D, MK[16], RK[16]); + round1(D, A, MK[15], RK[15]); round3(A, B, MK[14], RK[14]); + round2(B, C, MK[13], RK[13]); round1(C, D, MK[12], RK[12]); + round1(D, A, MK[11], RK[11]); round3(A, B, MK[10], RK[10]); + round2(B, C, MK[ 9], RK[ 9]); round1(C, D, MK[ 8], RK[ 8]); + round1(D, A, MK[ 7], RK[ 7]); round3(A, B, MK[ 6], RK[ 6]); + round2(B, C, MK[ 5], RK[ 5]); round1(C, D, MK[ 4], RK[ 4]); + round1(D, A, MK[ 3], RK[ 3]); round3(A, B, MK[ 2], RK[ 2]); + round2(B, C, MK[ 1], RK[ 1]); round1(C, D, MK[ 0], RK[ 0]); + + store_be(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/cast/cast256.h b/src/block/cast/cast256.h index cd48edd5e..1be7fa9cf 100644 --- a/src/block/cast/cast256.h +++ b/src/block/cast/cast256.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL CAST_256 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { MK.clear(); RK.clear(); } std::string name() const { return "CAST-256"; } BlockCipher* clone() const { return new CAST_256; } + CAST_256() : BlockCipher(16, 4, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const u32bit KEY_MASK[192]; diff --git a/src/block/des/des.cpp b/src/block/des/des.cpp index 37520e0fc..1c9d37e6b 100644 --- a/src/block/des/des.cpp +++ b/src/block/des/des.cpp @@ -139,51 +139,63 @@ void des_decrypt(u32bit& L, u32bit& R, /* * DES Encryption */ -void DES::enc(const byte in[], byte out[]) const +void DES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_encrypt(L, R, round_key); - des_encrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DES Decryption */ -void DES::dec(const byte in[], byte out[]) const +void DES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_decrypt(L, R, round_key); - des_decrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* @@ -197,55 +209,67 @@ void DES::key_schedule(const byte key[], u32bit) /* * TripleDES Encryption */ -void TripleDES::enc(const byte in[], byte out[]) const +void TripleDES::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_encrypt(L, R, round_key); + des_decrypt(R, L, round_key + 32); + des_encrypt(L, R, round_key + 64); - des_encrypt(L, R, round_key); - des_decrypt(R, L, round_key + 32); - des_encrypt(L, R, round_key + 64); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TripleDES Decryption */ -void TripleDES::dec(const byte in[], byte out[]) const +void TripleDES::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | - (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | - (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | - (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + for(u32bit i = 0; i != blocks; ++i) + { + u64bit T = (DES_IPTAB1[in[0]] ) | (DES_IPTAB1[in[1]] << 1) | + (DES_IPTAB1[in[2]] << 2) | (DES_IPTAB1[in[3]] << 3) | + (DES_IPTAB1[in[4]] << 4) | (DES_IPTAB1[in[5]] << 5) | + (DES_IPTAB1[in[6]] << 6) | (DES_IPTAB2[in[7]] ); + + u32bit L = static_cast<u32bit>(T >> 32); + u32bit R = static_cast<u32bit>(T); - u32bit L = static_cast<u32bit>(T >> 32); - u32bit R = static_cast<u32bit>(T); + des_decrypt(L, R, round_key + 64); + des_encrypt(R, L, round_key + 32); + des_decrypt(L, R, round_key); - des_decrypt(L, R, round_key + 64); - des_encrypt(R, L, round_key + 32); - des_decrypt(L, R, round_key); + T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | + (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | + (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | + (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); - T = (DES_FPTAB1[get_byte(0, L)] << 5) | (DES_FPTAB1[get_byte(1, L)] << 3) | - (DES_FPTAB1[get_byte(2, L)] << 1) | (DES_FPTAB2[get_byte(3, L)] << 1) | - (DES_FPTAB1[get_byte(0, R)] << 4) | (DES_FPTAB1[get_byte(1, R)] << 2) | - (DES_FPTAB1[get_byte(2, R)] ) | (DES_FPTAB2[get_byte(3, R)] ); + T = rotate_left(T, 32); - T = rotate_left(T, 32); + store_be(T, out); - store_be(T, out); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/des.h b/src/block/des/des.h index 6fa59de5e..856aaf60c 100644 --- a/src/block/des/des.h +++ b/src/block/des/des.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "DES"; } BlockCipher* clone() const { return new DES; } + DES() : BlockCipher(8, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 32> round_key; @@ -36,13 +38,15 @@ class BOTAN_DLL DES : public BlockCipher class BOTAN_DLL TripleDES : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "TripleDES"; } BlockCipher* clone() const { return new TripleDES; } + TripleDES() : BlockCipher(8, 16, 24, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 96> round_key; diff --git a/src/block/des/desx.cpp b/src/block/des/desx.cpp index e557901d3..1fc1c47f2 100644 --- a/src/block/des/desx.cpp +++ b/src/block/des/desx.cpp @@ -13,21 +13,33 @@ namespace Botan { /* * DESX Encryption */ -void DESX::enc(const byte in[], byte out[]) const +void DESX::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K1.begin(), BLOCK_SIZE); - des.encrypt(out); - xor_buf(out, K2.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K1.begin(), BLOCK_SIZE); + des.encrypt(out); + xor_buf(out, K2.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * DESX Decryption */ -void DESX::dec(const byte in[], byte out[]) const +void DESX::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - xor_buf(out, in, K2.begin(), BLOCK_SIZE); - des.decrypt(out); - xor_buf(out, K1.begin(), BLOCK_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(out, in, K2.begin(), BLOCK_SIZE); + des.decrypt(out); + xor_buf(out, K1.begin(), BLOCK_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/des/desx.h b/src/block/des/desx.h index 49ecc2421..d22895296 100644 --- a/src/block/des/desx.h +++ b/src/block/des/desx.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL DESX : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { des.clear(); K1.clear(); K2.clear(); } std::string name() const { return "DESX"; } BlockCipher* clone() const { return new DESX; } + DESX() : BlockCipher(8, 24) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<byte, 8> K1, K2; DES des; diff --git a/src/block/gost_28147/gost_28147.cpp b/src/block/gost_28147/gost_28147.cpp index bfd092c56..272f1bcab 100644 --- a/src/block/gost_28147/gost_28147.cpp +++ b/src/block/gost_28147/gost_28147.cpp @@ -84,47 +84,58 @@ GOST_28147_89::GOST_28147_89(const GOST_28147_89_Params& param) : /* * GOST Encryption */ -void GOST_28147_89::enc(const byte in[], byte out[]) const +void GOST_28147_89::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - - for(size_t i = 0; i != 3; ++i) + for(u32bit i = 0; i != blocks; ++i) { - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); - } + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); + for(size_t j = 0; j != 3; ++j) + { + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); + } - store_le(out, N2, N1); + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + + store_le(out, N2, N1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * GOST Decryption */ -void GOST_28147_89::dec(const byte in[], byte out[]) const +void GOST_28147_89::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1); - GOST_2ROUND(N1, N2, 0, 1); - GOST_2ROUND(N1, N2, 2, 3); - GOST_2ROUND(N1, N2, 4, 5); - GOST_2ROUND(N1, N2, 6, 7); + GOST_2ROUND(N1, N2, 0, 1); + GOST_2ROUND(N1, N2, 2, 3); + GOST_2ROUND(N1, N2, 4, 5); + GOST_2ROUND(N1, N2, 6, 7); - for(size_t i = 0; i != 3; ++i) - { - GOST_2ROUND(N1, N2, 7, 6); - GOST_2ROUND(N1, N2, 5, 4); - GOST_2ROUND(N1, N2, 3, 2); - GOST_2ROUND(N1, N2, 1, 0); - } + for(size_t i = 0; i != 3; ++i) + { + GOST_2ROUND(N1, N2, 7, 6); + GOST_2ROUND(N1, N2, 5, 4); + GOST_2ROUND(N1, N2, 3, 2); + GOST_2ROUND(N1, N2, 1, 0); + } - store_le(out, N2, N1); + store_le(out, N2, N1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/gost_28147/gost_28147.h b/src/block/gost_28147/gost_28147.h index 96d24c669..18c1d0a29 100644 --- a/src/block/gost_28147/gost_28147.h +++ b/src/block/gost_28147/gost_28147.h @@ -44,6 +44,9 @@ class GOST_28147_89_Params class BOTAN_DLL GOST_28147_89 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "GOST-28147-89"; } @@ -54,8 +57,6 @@ class BOTAN_DLL GOST_28147_89 : public BlockCipher GOST_28147_89(const SecureBuffer<u32bit, 1024>& other_SBOX) : BlockCipher(8, 32), SBOX(other_SBOX) {} - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 1024> SBOX; diff --git a/src/block/idea/idea.cpp b/src/block/idea/idea.cpp index 5bbe47087..fb5fe83f1 100644 --- a/src/block/idea/idea.cpp +++ b/src/block/idea/idea.cpp @@ -60,77 +60,89 @@ u16bit mul_inv(u16bit x) /* * IDEA Encryption */ -void IDEA::enc(const byte in[], byte out[]) const +void IDEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit X1 = load_be<u16bit>(in, 0); - u16bit X2 = load_be<u16bit>(in, 1); - u16bit X3 = load_be<u16bit>(in, 2); - u16bit X4 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; ++j) + for(u32bit i = 0; i != blocks; ++i) { - X1 = mul(X1, EK[6*j+0]); - X2 += EK[6*j+1]; - X3 += EK[6*j+2]; - X4 = mul(X4, EK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, EK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; + u16bit X1 = load_be<u16bit>(in, 0); + u16bit X2 = load_be<u16bit>(in, 1); + u16bit X3 = load_be<u16bit>(in, 2); + u16bit X4 = load_be<u16bit>(in, 3); + + for(u32bit j = 0; j != 8; ++j) + { + X1 = mul(X1, EK[6*j+0]); + X2 += EK[6*j+1]; + X3 += EK[6*j+2]; + X4 = mul(X4, EK[6*j+3]); + + u16bit T0 = X3; + X3 = mul(X3 ^ X1, EK[6*j+4]); + + u16bit T1 = X2; + X2 = mul((X2 ^ X4) + X3, EK[6*j+5]); + X3 += X2; + + X1 ^= X2; + X4 ^= X3; + X2 ^= T0; + X3 ^= T1; + } + + X1 = mul(X1, EK[48]); + X2 += EK[50]; + X3 += EK[49]; + X4 = mul(X4, EK[51]); + + store_be(out, X1, X3, X2, X4); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - X1 = mul(X1, EK[48]); - X2 += EK[50]; - X3 += EK[49]; - X4 = mul(X4, EK[51]); - - store_be(out, X1, X3, X2, X4); } /* * IDEA Decryption */ -void IDEA::dec(const byte in[], byte out[]) const +void IDEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit X1 = load_be<u16bit>(in, 0); - u16bit X2 = load_be<u16bit>(in, 1); - u16bit X3 = load_be<u16bit>(in, 2); - u16bit X4 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; ++j) + for(u32bit i = 0; i != blocks; ++i) { - X1 = mul(X1, DK[6*j+0]); - X2 += DK[6*j+1]; - X3 += DK[6*j+2]; - X4 = mul(X4, DK[6*j+3]); - - u16bit T0 = X3; - X3 = mul(X3 ^ X1, DK[6*j+4]); - - u16bit T1 = X2; - X2 = mul((X2 ^ X4) + X3, DK[6*j+5]); - X3 += X2; - - X1 ^= X2; - X4 ^= X3; - X2 ^= T0; - X3 ^= T1; + u16bit X1 = load_be<u16bit>(in, 0); + u16bit X2 = load_be<u16bit>(in, 1); + u16bit X3 = load_be<u16bit>(in, 2); + u16bit X4 = load_be<u16bit>(in, 3); + + for(u32bit j = 0; j != 8; ++j) + { + X1 = mul(X1, DK[6*j+0]); + X2 += DK[6*j+1]; + X3 += DK[6*j+2]; + X4 = mul(X4, DK[6*j+3]); + + u16bit T0 = X3; + X3 = mul(X3 ^ X1, DK[6*j+4]); + + u16bit T1 = X2; + X2 = mul((X2 ^ X4) + X3, DK[6*j+5]); + X3 += X2; + + X1 ^= X2; + X4 ^= X3; + X2 ^= T0; + X3 ^= T1; + } + + X1 = mul(X1, DK[48]); + X2 += DK[50]; + X3 += DK[49]; + X4 = mul(X4, DK[51]); + + store_be(out, X1, X3, X2, X4); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - X1 = mul(X1, DK[48]); - X2 += DK[50]; - X3 += DK[49]; - X4 = mul(X4, DK[51]); - - store_be(out, X1, X3, X2, X4); } /* diff --git a/src/block/idea/idea.h b/src/block/idea/idea.h index 2c53cd0e4..59484531b 100644 --- a/src/block/idea/idea.h +++ b/src/block/idea/idea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL IDEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "IDEA"; } BlockCipher* clone() const { return new IDEA; } + IDEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 52> EK, DK; }; diff --git a/src/block/kasumi/kasumi.cpp b/src/block/kasumi/kasumi.cpp index e051ddefb..dff6db13c 100644 --- a/src/block/kasumi/kasumi.cpp +++ b/src/block/kasumi/kasumi.cpp @@ -109,79 +109,91 @@ u16bit FI(u16bit I, u16bit K) /* * KASUMI Encryption */ -void KASUMI::enc(const byte in[], byte out[]) const +void KASUMI::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); - u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*j; - L = FI(L ^ K[ 2], K[ 3]) ^ R; - R = FI(R ^ K[ 4], K[ 5]) ^ L; - L = FI(L ^ K[ 6], K[ 7]) ^ R; + u16bit R = B1 ^ (rotate_left(B0, 1) & K[0]); + u16bit L = B0 ^ (rotate_left(R, 1) | K[1]); - R = B2 ^= R; - L = B3 ^= L; + L = FI(L ^ K[ 2], K[ 3]) ^ R; + R = FI(R ^ K[ 4], K[ 5]) ^ L; + L = FI(L ^ K[ 6], K[ 7]) ^ R; - R = FI(R ^ K[10], K[11]) ^ L; - L = FI(L ^ K[12], K[13]) ^ R; - R = FI(R ^ K[14], K[15]) ^ L; + R = B2 ^= R; + L = B3 ^= L; - R ^= (rotate_left(L, 1) & K[8]); - L ^= (rotate_left(R, 1) | K[9]); + R = FI(R ^ K[10], K[11]) ^ L; + L = FI(L ^ K[12], K[13]) ^ R; + R = FI(R ^ K[14], K[15]) ^ L; - B0 ^= L; - B1 ^= R; - } + R ^= (rotate_left(L, 1) & K[8]); + L ^= (rotate_left(R, 1) | K[9]); + + B0 ^= L; + B1 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * KASUMI Decryption */ -void KASUMI::dec(const byte in[], byte out[]) const +void KASUMI::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 8; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* K = EK + 8*(6-j); + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - u16bit L = B2, R = B3; + for(u32bit j = 0; j != 8; j += 2) + { + const u16bit* K = EK + 8*(6-j); - L = FI(L ^ K[10], K[11]) ^ R; - R = FI(R ^ K[12], K[13]) ^ L; - L = FI(L ^ K[14], K[15]) ^ R; + u16bit L = B2, R = B3; - L ^= (rotate_left(R, 1) & K[8]); - R ^= (rotate_left(L, 1) | K[9]); + L = FI(L ^ K[10], K[11]) ^ R; + R = FI(R ^ K[12], K[13]) ^ L; + L = FI(L ^ K[14], K[15]) ^ R; - R = B0 ^= R; - L = B1 ^= L; + L ^= (rotate_left(R, 1) & K[8]); + R ^= (rotate_left(L, 1) | K[9]); - L ^= (rotate_left(R, 1) & K[0]); - R ^= (rotate_left(L, 1) | K[1]); + R = B0 ^= R; + L = B1 ^= L; - R = FI(R ^ K[2], K[3]) ^ L; - L = FI(L ^ K[4], K[5]) ^ R; - R = FI(R ^ K[6], K[7]) ^ L; + L ^= (rotate_left(R, 1) & K[0]); + R ^= (rotate_left(L, 1) | K[1]); - B2 ^= L; - B3 ^= R; - } + R = FI(R ^ K[2], K[3]) ^ L; + L = FI(L ^ K[4], K[5]) ^ R; + R = FI(R ^ K[6], K[7]) ^ L; + + B2 ^= L; + B3 ^= R; + } - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/kasumi/kasumi.h b/src/block/kasumi/kasumi.h index df49fa9eb..0f5a5d182 100644 --- a/src/block/kasumi/kasumi.h +++ b/src/block/kasumi/kasumi.h @@ -18,14 +18,15 @@ namespace Botan { class BOTAN_DLL KASUMI : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "KASUMI"; } BlockCipher* clone() const { return new KASUMI; } KASUMI() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> EK; diff --git a/src/block/lion/lion.cpp b/src/block/lion/lion.cpp index c7cdf6d13..83c1e3aa3 100644 --- a/src/block/lion/lion.cpp +++ b/src/block/lion/lion.cpp @@ -14,41 +14,53 @@ namespace Botan { /* * Lion Encryption */ -void Lion::enc(const byte in[], byte out[]) const +void Lion::encrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - xor_buf(buffer, out, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + xor_buf(buffer, out, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Lion Decryption */ -void Lion::dec(const byte in[], byte out[]) const +void Lion::decrypt_n(const byte in[], byte out[], u32bit blocks) const { SecureVector<byte> buffer(LEFT_SIZE); - xor_buf(buffer, in, key2, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + for(u32bit i = 0; i != blocks; ++i) + { + xor_buf(buffer, in, key2, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(in + LEFT_SIZE, out + LEFT_SIZE, RIGHT_SIZE); + + hash->update(out + LEFT_SIZE, RIGHT_SIZE); + hash->final(buffer); + xor_buf(out, in, buffer, LEFT_SIZE); - hash->update(out + LEFT_SIZE, RIGHT_SIZE); - hash->final(buffer); - xor_buf(out, in, buffer, LEFT_SIZE); + xor_buf(buffer, out, key1, LEFT_SIZE); + cipher->set_key(buffer, LEFT_SIZE); + cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); - xor_buf(buffer, out, key1, LEFT_SIZE); - cipher->set_key(buffer, LEFT_SIZE); - cipher->encrypt(out + LEFT_SIZE, RIGHT_SIZE); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lion/lion.h b/src/block/lion/lion.h index 5bc4e72c0..d421771d6 100644 --- a/src/block/lion/lion.h +++ b/src/block/lion/lion.h @@ -20,6 +20,9 @@ namespace Botan { class BOTAN_DLL Lion : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -27,8 +30,6 @@ class BOTAN_DLL Lion : public BlockCipher Lion(HashFunction*, StreamCipher*, u32bit); ~Lion() { delete hash; delete cipher; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); const u32bit LEFT_SIZE, RIGHT_SIZE; diff --git a/src/block/lubyrack/lubyrack.cpp b/src/block/lubyrack/lubyrack.cpp index a9d2b1db2..6ad64f2b0 100644 --- a/src/block/lubyrack/lubyrack.cpp +++ b/src/block/lubyrack/lubyrack.cpp @@ -13,59 +13,71 @@ namespace Botan { /* * Luby-Rackoff Encryption */ -void LubyRackoff::enc(const byte in[], byte out[]) const +void LubyRackoff::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K1); - hash->update(in, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K1); + hash->update(in, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Luby-Rackoff Decryption */ -void LubyRackoff::dec(const byte in[], byte out[]) const +void LubyRackoff::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - const u32bit len = hash->OUTPUT_LENGTH; - - SecureVector<byte> buffer(len); - hash->update(K2); - hash->update(in + len, len); - hash->final(buffer); - xor_buf(out, in, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, in + len, buffer, len); - - hash->update(K2); - hash->update(out + len, len); - hash->final(buffer); - xor_buf(out, buffer, len); - - hash->update(K1); - hash->update(out, len); - hash->final(buffer); - xor_buf(out + len, buffer, len); + for(u32bit i = 0; i != blocks; ++i) + { + const u32bit len = hash->OUTPUT_LENGTH; + + SecureVector<byte> buffer(len); + hash->update(K2); + hash->update(in + len, len); + hash->final(buffer); + xor_buf(out, in, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, in + len, buffer, len); + + hash->update(K2); + hash->update(out + len, len); + hash->final(buffer); + xor_buf(out, buffer, len); + + hash->update(K1); + hash->update(out, len); + hash->final(buffer); + xor_buf(out + len, buffer, len); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/lubyrack/lubyrack.h b/src/block/lubyrack/lubyrack.h index ebde31304..940b34603 100644 --- a/src/block/lubyrack/lubyrack.h +++ b/src/block/lubyrack/lubyrack.h @@ -19,6 +19,9 @@ namespace Botan { class BOTAN_DLL LubyRackoff : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const; BlockCipher* clone() const; @@ -26,9 +29,8 @@ class BOTAN_DLL LubyRackoff : public BlockCipher LubyRackoff(HashFunction* hash); ~LubyRackoff() { delete hash; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); + HashFunction* hash; SecureVector<byte> K1, K2; }; diff --git a/src/block/mars/mars.cpp b/src/block/mars/mars.cpp index 08c8409c5..69556acb3 100644 --- a/src/block/mars/mars.cpp +++ b/src/block/mars/mars.cpp @@ -1,6 +1,6 @@ /* * MARS -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -50,75 +50,87 @@ u32bit gen_mask(u32bit input) /* * MARS Encryption */ -void MARS::enc(const byte in[], byte out[]) const +void MARS::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) + EK[0]; - u32bit B = load_le<u32bit>(in, 1) + EK[1]; - u32bit C = load_le<u32bit>(in, 2) + EK[2]; - u32bit D = load_le<u32bit>(in, 3) + EK[3]; - - forward_mix(A, B, C, D); - - encrypt_round(A, B, C, D, 0); - encrypt_round(B, C, D, A, 1); - encrypt_round(C, D, A, B, 2); - encrypt_round(D, A, B, C, 3); - encrypt_round(A, B, C, D, 4); - encrypt_round(B, C, D, A, 5); - encrypt_round(C, D, A, B, 6); - encrypt_round(D, A, B, C, 7); - - encrypt_round(A, D, C, B, 8); - encrypt_round(B, A, D, C, 9); - encrypt_round(C, B, A, D, 10); - encrypt_round(D, C, B, A, 11); - encrypt_round(A, D, C, B, 12); - encrypt_round(B, A, D, C, 13); - encrypt_round(C, B, A, D, 14); - encrypt_round(D, C, B, A, 15); - - reverse_mix(A, B, C, D); - - A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; - - store_le(out, A, B, C, D); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0) + EK[0]; + u32bit B = load_le<u32bit>(in, 1) + EK[1]; + u32bit C = load_le<u32bit>(in, 2) + EK[2]; + u32bit D = load_le<u32bit>(in, 3) + EK[3]; + + forward_mix(A, B, C, D); + + encrypt_round(A, B, C, D, 0); + encrypt_round(B, C, D, A, 1); + encrypt_round(C, D, A, B, 2); + encrypt_round(D, A, B, C, 3); + encrypt_round(A, B, C, D, 4); + encrypt_round(B, C, D, A, 5); + encrypt_round(C, D, A, B, 6); + encrypt_round(D, A, B, C, 7); + + encrypt_round(A, D, C, B, 8); + encrypt_round(B, A, D, C, 9); + encrypt_round(C, B, A, D, 10); + encrypt_round(D, C, B, A, 11); + encrypt_round(A, D, C, B, 12); + encrypt_round(B, A, D, C, 13); + encrypt_round(C, B, A, D, 14); + encrypt_round(D, C, B, A, 15); + + reverse_mix(A, B, C, D); + + A -= EK[36]; B -= EK[37]; C -= EK[38]; D -= EK[39]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MARS Decryption */ -void MARS::dec(const byte in[], byte out[]) const +void MARS::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 3) + EK[39]; - u32bit B = load_le<u32bit>(in, 2) + EK[38]; - u32bit C = load_le<u32bit>(in, 1) + EK[37]; - u32bit D = load_le<u32bit>(in, 0) + EK[36]; - - forward_mix(A, B, C, D); - - decrypt_round(A, B, C, D, 15); - decrypt_round(B, C, D, A, 14); - decrypt_round(C, D, A, B, 13); - decrypt_round(D, A, B, C, 12); - decrypt_round(A, B, C, D, 11); - decrypt_round(B, C, D, A, 10); - decrypt_round(C, D, A, B, 9); - decrypt_round(D, A, B, C, 8); - - decrypt_round(A, D, C, B, 7); - decrypt_round(B, A, D, C, 6); - decrypt_round(C, B, A, D, 5); - decrypt_round(D, C, B, A, 4); - decrypt_round(A, D, C, B, 3); - decrypt_round(B, A, D, C, 2); - decrypt_round(C, B, A, D, 1); - decrypt_round(D, C, B, A, 0); - - reverse_mix(A, B, C, D); - - A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; - - store_le(out, D, C, B, A); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 3) + EK[39]; + u32bit B = load_le<u32bit>(in, 2) + EK[38]; + u32bit C = load_le<u32bit>(in, 1) + EK[37]; + u32bit D = load_le<u32bit>(in, 0) + EK[36]; + + forward_mix(A, B, C, D); + + decrypt_round(A, B, C, D, 15); + decrypt_round(B, C, D, A, 14); + decrypt_round(C, D, A, B, 13); + decrypt_round(D, A, B, C, 12); + decrypt_round(A, B, C, D, 11); + decrypt_round(B, C, D, A, 10); + decrypt_round(C, D, A, B, 9); + decrypt_round(D, A, B, C, 8); + + decrypt_round(A, D, C, B, 7); + decrypt_round(B, A, D, C, 6); + decrypt_round(C, B, A, D, 5); + decrypt_round(D, C, B, A, 4); + decrypt_round(A, D, C, B, 3); + decrypt_round(B, A, D, C, 2); + decrypt_round(C, B, A, D, 1); + decrypt_round(D, C, B, A, 0); + + reverse_mix(A, B, C, D); + + A -= EK[3]; B -= EK[2]; C -= EK[1]; D -= EK[0]; + + store_le(out, D, C, B, A); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/mars/mars.h b/src/block/mars/mars.h index ca49695af..7d0bfe4fa 100644 --- a/src/block/mars/mars.h +++ b/src/block/mars/mars.h @@ -15,13 +15,15 @@ namespace Botan { class BOTAN_DLL MARS : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "MARS"; } BlockCipher* clone() const { return new MARS; } + MARS() : BlockCipher(16, 16, 32, 4) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void encrypt_round(u32bit&, u32bit&, u32bit&, u32bit&, u32bit) const; diff --git a/src/block/misty1/misty1.cpp b/src/block/misty1/misty1.cpp index a35ff584d..8a92824cc 100644 --- a/src/block/misty1/misty1.cpp +++ b/src/block/misty1/misty1.cpp @@ -1,6 +1,6 @@ /* * MISTY1 -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -102,89 +102,101 @@ u16bit FI(u16bit input, u16bit key7, u16bit key9) /* * MISTY1 Encryption */ -void MISTY1::enc(const byte in[], byte out[]) const +void MISTY1::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 0); - u16bit B1 = load_be<u16bit>(in, 1); - u16bit B2 = load_be<u16bit>(in, 2); - u16bit B3 = load_be<u16bit>(in, 3); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = EK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 0); + u16bit B1 = load_be<u16bit>(in, 1); + u16bit B2 = load_be<u16bit>(in, 2); + u16bit B3 = load_be<u16bit>(in, 3); - B1 ^= B0 & RK[0]; - B0 ^= B1 | RK[1]; - B3 ^= B2 & RK[2]; - B2 ^= B3 | RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = EK + 8 * j; - u32bit T0, T1; + B1 ^= B0 & RK[0]; + B0 ^= B1 | RK[1]; + B3 ^= B2 & RK[2]; + B2 ^= B3 | RK[3]; - T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; - T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B2 ^= T1 ^ RK[13]; - B3 ^= T0; + T0 = FI(B0 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B1; + T1 = FI(B1 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; - T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B2 ^= T1 ^ RK[13]; + B3 ^= T0; - B0 ^= T1 ^ RK[23]; - B1 ^= T0; - } + T0 = FI(B2 ^ RK[14], RK[15], RK[16]) ^ B3; + T1 = FI(B3 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B0 ^= T1 ^ RK[23]; + B1 ^= T0; + } - B1 ^= B0 & EK[96]; - B0 ^= B1 | EK[97]; - B3 ^= B2 & EK[98]; - B2 ^= B3 | EK[99]; + B1 ^= B0 & EK[96]; + B0 ^= B1 | EK[97]; + B3 ^= B2 & EK[98]; + B2 ^= B3 | EK[99]; - store_be(out, B2, B3, B0, B1); + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * MISTY1 Decryption */ -void MISTY1::dec(const byte in[], byte out[]) const +void MISTY1::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit B0 = load_be<u16bit>(in, 2); - u16bit B1 = load_be<u16bit>(in, 3); - u16bit B2 = load_be<u16bit>(in, 0); - u16bit B3 = load_be<u16bit>(in, 1); - - for(u32bit j = 0; j != 12; j += 3) + for(u32bit i = 0; i != blocks; ++i) { - const u16bit* RK = DK + 8 * j; + u16bit B0 = load_be<u16bit>(in, 2); + u16bit B1 = load_be<u16bit>(in, 3); + u16bit B2 = load_be<u16bit>(in, 0); + u16bit B3 = load_be<u16bit>(in, 1); - B2 ^= B3 | RK[0]; - B3 ^= B2 & RK[1]; - B0 ^= B1 | RK[2]; - B1 ^= B0 & RK[3]; + for(u32bit j = 0; j != 12; j += 3) + { + const u16bit* RK = DK + 8 * j; - u32bit T0, T1; + B2 ^= B3 | RK[0]; + B3 ^= B2 & RK[1]; + B0 ^= B1 | RK[2]; + B1 ^= B0 & RK[3]; - T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; - T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; - T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; + u32bit T0, T1; - B0 ^= T1 ^ RK[13]; - B1 ^= T0; + T0 = FI(B2 ^ RK[ 4], RK[ 5], RK[ 6]) ^ B3; + T1 = FI(B3 ^ RK[ 7], RK[ 8], RK[ 9]) ^ T0; + T0 = FI(T0 ^ RK[10], RK[11], RK[12]) ^ T1; - T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; - T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; - T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + B0 ^= T1 ^ RK[13]; + B1 ^= T0; - B2 ^= T1 ^ RK[23]; - B3 ^= T0; - } + T0 = FI(B0 ^ RK[14], RK[15], RK[16]) ^ B1; + T1 = FI(B1 ^ RK[17], RK[18], RK[19]) ^ T0; + T0 = FI(T0 ^ RK[20], RK[21], RK[22]) ^ T1; + + B2 ^= T1 ^ RK[23]; + B3 ^= T0; + } - B2 ^= B3 | DK[96]; - B3 ^= B2 & DK[97]; - B0 ^= B1 | DK[98]; - B1 ^= B0 & DK[99]; + B2 ^= B3 | DK[96]; + B3 ^= B2 & DK[97]; + B0 ^= B1 | DK[98]; + B1 ^= B0 & DK[99]; - store_be(out, B0, B1, B2, B3); + store_be(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/misty1/misty1.h b/src/block/misty1/misty1.h index 62d4f856f..8db6881de 100644 --- a/src/block/misty1/misty1.h +++ b/src/block/misty1/misty1.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL MISTY1 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); DK.clear(); } std::string name() const { return "MISTY1"; } BlockCipher* clone() const { return new MISTY1; } + MISTY1(u32bit = 8); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 100> EK, DK; diff --git a/src/block/noekeon/noekeon.cpp b/src/block/noekeon/noekeon.cpp index 90eb9ad2b..1b327aa47 100644 --- a/src/block/noekeon/noekeon.cpp +++ b/src/block/noekeon/noekeon.cpp @@ -84,65 +84,77 @@ const byte Noekeon::RC[] = { /* * Noekeon Encryption */ -void Noekeon::enc(const byte in[], byte out[]) const +void Noekeon::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - A0 ^= RC[j]; - theta(A0, A1, A2, A3, EK); + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 0; j != 16; ++j) + { + A0 ^= RC[j]; + theta(A0, A1, A2, A3, EK); - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - A0 ^= RC[16]; - theta(A0, A1, A2, A3, EK); + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } + + A0 ^= RC[16]; + theta(A0, A1, A2, A3, EK); + + store_be(out, A0, A1, A2, A3); - store_be(out, A0, A1, A2, A3); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Noekeon Encryption */ -void Noekeon::dec(const byte in[], byte out[]) const +void Noekeon::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A0 = load_be<u32bit>(in, 0); - u32bit A1 = load_be<u32bit>(in, 1); - u32bit A2 = load_be<u32bit>(in, 2); - u32bit A3 = load_be<u32bit>(in, 3); - - for(u32bit j = 16; j != 0; --j) + for(u32bit i = 0; i != blocks; ++i) { - theta(A0, A1, A2, A3, DK); - A0 ^= RC[j]; + u32bit A0 = load_be<u32bit>(in, 0); + u32bit A1 = load_be<u32bit>(in, 1); + u32bit A2 = load_be<u32bit>(in, 2); + u32bit A3 = load_be<u32bit>(in, 3); - A1 = rotate_left(A1, 1); - A2 = rotate_left(A2, 5); - A3 = rotate_left(A3, 2); + for(u32bit j = 16; j != 0; --j) + { + theta(A0, A1, A2, A3, DK); + A0 ^= RC[j]; - gamma(A0, A1, A2, A3); + A1 = rotate_left(A1, 1); + A2 = rotate_left(A2, 5); + A3 = rotate_left(A3, 2); - A1 = rotate_right(A1, 1); - A2 = rotate_right(A2, 5); - A3 = rotate_right(A3, 2); - } + gamma(A0, A1, A2, A3); - theta(A0, A1, A2, A3, DK); - A0 ^= RC[0]; + A1 = rotate_right(A1, 1); + A2 = rotate_right(A2, 5); + A3 = rotate_right(A3, 2); + } - store_be(out, A0, A1, A2, A3); + theta(A0, A1, A2, A3, DK); + A0 ^= RC[0]; + + store_be(out, A0, A1, A2, A3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/noekeon/noekeon.h b/src/block/noekeon/noekeon.h index 893892446..37b24fb7d 100644 --- a/src/block/noekeon/noekeon.h +++ b/src/block/noekeon/noekeon.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Noekeon : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Noekeon"; } BlockCipher* clone() const { return new Noekeon; } + Noekeon() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte RC[17]; diff --git a/src/block/rc2/rc2.cpp b/src/block/rc2/rc2.cpp index 5827bdb68..b5e4a7d50 100644 --- a/src/block/rc2/rc2.cpp +++ b/src/block/rc2/rc2.cpp @@ -14,73 +14,85 @@ namespace Botan { /* * RC2 Encryption */ -void RC2::enc(const byte in[], byte out[]) const +void RC2::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; - R0 = rotate_left(R0, 1); + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R0 += (R1 & ~R3) + (R2 & R3) + K[4*j]; + R0 = rotate_left(R0, 1); - R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; - R1 = rotate_left(R1, 2); + R1 += (R2 & ~R0) + (R3 & R0) + K[4*j + 1]; + R1 = rotate_left(R1, 2); - R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; - R2 = rotate_left(R2, 3); + R2 += (R3 & ~R1) + (R0 & R1) + K[4*j + 2]; + R2 = rotate_left(R2, 3); - R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; - R3 = rotate_left(R3, 5); + R3 += (R0 & ~R2) + (R1 & R2) + K[4*j + 3]; + R3 = rotate_left(R3, 5); - if(j == 4 || j == 10) - { - R0 += K[R3 % 64]; - R1 += K[R0 % 64]; - R2 += K[R1 % 64]; - R3 += K[R2 % 64]; + if(j == 4 || j == 10) + { + R0 += K[R3 % 64]; + R1 += K[R0 % 64]; + R2 += K[R1 % 64]; + R3 += K[R2 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC2 Decryption */ -void RC2::dec(const byte in[], byte out[]) const +void RC2::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit R0 = load_le<u16bit>(in, 0); - u16bit R1 = load_le<u16bit>(in, 1); - u16bit R2 = load_le<u16bit>(in, 2); - u16bit R3 = load_le<u16bit>(in, 3); - - for(u32bit j = 0; j != 16; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R3 = rotate_right(R3, 5); - R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; + u16bit R0 = load_le<u16bit>(in, 0); + u16bit R1 = load_le<u16bit>(in, 1); + u16bit R2 = load_le<u16bit>(in, 2); + u16bit R3 = load_le<u16bit>(in, 3); + + for(u32bit j = 0; j != 16; ++j) + { + R3 = rotate_right(R3, 5); + R3 -= (R0 & ~R2) + (R1 & R2) + K[63 - (4*j + 0)]; - R2 = rotate_right(R2, 3); - R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; + R2 = rotate_right(R2, 3); + R2 -= (R3 & ~R1) + (R0 & R1) + K[63 - (4*j + 1)]; - R1 = rotate_right(R1, 2); - R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; + R1 = rotate_right(R1, 2); + R1 -= (R2 & ~R0) + (R3 & R0) + K[63 - (4*j + 2)]; - R0 = rotate_right(R0, 1); - R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; + R0 = rotate_right(R0, 1); + R0 -= (R1 & ~R3) + (R2 & R3) + K[63 - (4*j + 3)]; - if(j == 4 || j == 10) - { - R3 -= K[R2 % 64]; - R2 -= K[R1 % 64]; - R1 -= K[R0 % 64]; - R0 -= K[R3 % 64]; + if(j == 4 || j == 10) + { + R3 -= K[R2 % 64]; + R2 -= K[R1 % 64]; + R1 -= K[R0 % 64]; + R0 -= K[R3 % 64]; + } } - } - store_le(out, R0, R1, R2, R3); + store_le(out, R0, R1, R2, R3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc2/rc2.h b/src/block/rc2/rc2.h index cb6f58f04..db623b385 100644 --- a/src/block/rc2/rc2.h +++ b/src/block/rc2/rc2.h @@ -18,15 +18,17 @@ namespace Botan { class BOTAN_DLL RC2 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + static byte EKB_code(u32bit); void clear() throw() { K.clear(); } std::string name() const { return "RC2"; } BlockCipher* clone() const { return new RC2; } + RC2() : BlockCipher(8, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u16bit, 64> K; diff --git a/src/block/rc5/rc5.cpp b/src/block/rc5/rc5.cpp index 5d83d5a4e..4bfa27ea0 100644 --- a/src/block/rc5/rc5.cpp +++ b/src/block/rc5/rc5.cpp @@ -16,47 +16,59 @@ namespace Botan { /* * RC5 Encryption */ -void RC5::enc(const byte in[], byte out[]) const +void RC5::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - A += S[0]; B += S[1]; - for(u32bit j = 0; j != ROUNDS; j += 4) + for(u32bit i = 0; i != blocks; ++i) { - A = rotate_left(A ^ B, B % 32) + S[2*j+2]; - B = rotate_left(B ^ A, A % 32) + S[2*j+3]; - A = rotate_left(A ^ B, B % 32) + S[2*j+4]; - B = rotate_left(B ^ A, A % 32) + S[2*j+5]; - A = rotate_left(A ^ B, B % 32) + S[2*j+6]; - B = rotate_left(B ^ A, A % 32) + S[2*j+7]; - A = rotate_left(A ^ B, B % 32) + S[2*j+8]; - B = rotate_left(B ^ A, A % 32) + S[2*j+9]; - } + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + A += S[0]; B += S[1]; + for(u32bit j = 0; j != ROUNDS; j += 4) + { + A = rotate_left(A ^ B, B % 32) + S[2*j+2]; + B = rotate_left(B ^ A, A % 32) + S[2*j+3]; + A = rotate_left(A ^ B, B % 32) + S[2*j+4]; + B = rotate_left(B ^ A, A % 32) + S[2*j+5]; + A = rotate_left(A ^ B, B % 32) + S[2*j+6]; + B = rotate_left(B ^ A, A % 32) + S[2*j+7]; + A = rotate_left(A ^ B, B % 32) + S[2*j+8]; + B = rotate_left(B ^ A, A % 32) + S[2*j+9]; + } - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC5 Decryption */ -void RC5::dec(const byte in[], byte out[]) const +void RC5::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); - - for(u32bit j = ROUNDS; j != 0; j -= 4) + for(u32bit i = 0; i != blocks; ++i) { - B = rotate_right(B - S[2*j+1], A % 32) ^ A; - A = rotate_right(A - S[2*j ], B % 32) ^ B; - B = rotate_right(B - S[2*j-1], A % 32) ^ A; - A = rotate_right(A - S[2*j-2], B % 32) ^ B; - B = rotate_right(B - S[2*j-3], A % 32) ^ A; - A = rotate_right(A - S[2*j-4], B % 32) ^ B; - B = rotate_right(B - S[2*j-5], A % 32) ^ A; - A = rotate_right(A - S[2*j-6], B % 32) ^ B; - } - B -= S[1]; A -= S[0]; + u32bit A = load_le<u32bit>(in, 0), B = load_le<u32bit>(in, 1); + + for(u32bit j = ROUNDS; j != 0; j -= 4) + { + B = rotate_right(B - S[2*j+1], A % 32) ^ A; + A = rotate_right(A - S[2*j ], B % 32) ^ B; + B = rotate_right(B - S[2*j-1], A % 32) ^ A; + A = rotate_right(A - S[2*j-2], B % 32) ^ B; + B = rotate_right(B - S[2*j-3], A % 32) ^ A; + A = rotate_right(A - S[2*j-4], B % 32) ^ B; + B = rotate_right(B - S[2*j-5], A % 32) ^ A; + A = rotate_right(A - S[2*j-6], B % 32) ^ B; + } + B -= S[1]; A -= S[0]; - store_le(out, A, B); + store_le(out, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc5/rc5.h b/src/block/rc5/rc5.h index 083224720..ff9204710 100644 --- a/src/block/rc5/rc5.h +++ b/src/block/rc5/rc5.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC5 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const; BlockCipher* clone() const { return new RC5(ROUNDS); } + RC5(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureVector<u32bit> S; const u32bit ROUNDS; diff --git a/src/block/rc6/rc6.cpp b/src/block/rc6/rc6.cpp index 3b30ea93a..8bda62259 100644 --- a/src/block/rc6/rc6.cpp +++ b/src/block/rc6/rc6.cpp @@ -15,85 +15,97 @@ namespace Botan { /* * RC6 Encryption */ -void RC6::enc(const byte in[], byte out[]) const +void RC6::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - B += S[0]; D += S[1]; + B += S[0]; D += S[1]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; - C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; - D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; - A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; - B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; + C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; + + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; + D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; - A += S[42]; C += S[43]; + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; + A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; - store_le(out, A, B, C, D); + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; + B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; + } + + A += S[42]; C += S[43]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * RC6 Decryption */ -void RC6::dec(const byte in[], byte out[]) const +void RC6::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0); - u32bit B = load_le<u32bit>(in, 1); - u32bit C = load_le<u32bit>(in, 2); - u32bit D = load_le<u32bit>(in, 3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit A = load_le<u32bit>(in, 0); + u32bit B = load_le<u32bit>(in, 1); + u32bit C = load_le<u32bit>(in, 2); + u32bit D = load_le<u32bit>(in, 3); - C -= S[43]; A -= S[42]; + C -= S[43]; A -= S[42]; - for(u32bit j = 0; j != 20; j += 4) - { - u32bit T1, T2; - - T1 = rotate_left(A*(2*A+1), 5); - T2 = rotate_left(C*(2*C+1), 5); - B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; - D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(D*(2*D+1), 5); - T2 = rotate_left(B*(2*B+1), 5); - A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; - C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(C*(2*C+1), 5); - T2 = rotate_left(A*(2*A+1), 5); - D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; - B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - - T1 = rotate_left(B*(2*B+1), 5); - T2 = rotate_left(D*(2*D+1), 5); - C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; - A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; - } + for(u32bit j = 0; j != 20; j += 4) + { + u32bit T1, T2; + + T1 = rotate_left(A*(2*A+1), 5); + T2 = rotate_left(C*(2*C+1), 5); + B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; + D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; + + T1 = rotate_left(D*(2*D+1), 5); + T2 = rotate_left(B*(2*B+1), 5); + A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; + C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; - D -= S[1]; B -= S[0]; + T1 = rotate_left(C*(2*C+1), 5); + T2 = rotate_left(A*(2*A+1), 5); + D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; + B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; - store_le(out, A, B, C, D); + T1 = rotate_left(B*(2*B+1), 5); + T2 = rotate_left(D*(2*D+1), 5); + C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; + A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; + } + + D -= S[1]; B -= S[0]; + + store_le(out, A, B, C, D); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/rc6/rc6.h b/src/block/rc6/rc6.h index cb2800be7..5171006f5 100644 --- a/src/block/rc6/rc6.h +++ b/src/block/rc6/rc6.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL RC6 : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { S.clear(); } std::string name() const { return "RC6"; } BlockCipher* clone() const { return new RC6; } + RC6() : BlockCipher(16, 1, 32) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 44> S; diff --git a/src/block/safer/safer_sk.cpp b/src/block/safer/safer_sk.cpp index f72c4773b..eb5c22fc9 100644 --- a/src/block/safer/safer_sk.cpp +++ b/src/block/safer/safer_sk.cpp @@ -1,6 +1,6 @@ /* * SAFER-SK -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -15,54 +15,75 @@ namespace Botan { /* * SAFER-SK Encryption */ -void SAFER_SK::enc(const byte in[], byte out[]) const +void SAFER_SK::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7], X, Y; - for(u32bit j = 0; j != 16*ROUNDS; j += 16) + for(u32bit i = 0; i != blocks; ++i) { - A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; - C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; - E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; - G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; - A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; - E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; - B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; - C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; - H += D; Y = D + H; D = B + F; X = B + D; B = A + E; - A += B; F = C + G; E = C + F; C = X; G = Y; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7], X, Y; + + for(u32bit j = 0; j != 16*ROUNDS; j += 16) + { + A = EXP[A ^ EK[j ]]; B = LOG[B + EK[j+1]]; + C = LOG[C + EK[j+2]]; D = EXP[D ^ EK[j+3]]; + E = EXP[E ^ EK[j+4]]; F = LOG[F + EK[j+5]]; + G = LOG[G + EK[j+6]]; H = EXP[H ^ EK[j+7]]; + + A += EK[j+ 8]; B ^= EK[j+ 9]; C ^= EK[j+10]; D += EK[j+11]; + E += EK[j+12]; F ^= EK[j+13]; G ^= EK[j+14]; H += EK[j+15]; + + B += A; D += C; F += E; H += G; A += B; C += D; E += F; G += H; + C += A; G += E; D += B; H += F; A += C; E += G; B += D; F += H; + H += D; Y = D + H; D = B + F; X = B + D; B = A + E; + A += B; F = C + G; E = C + F; C = X; G = Y; + } + + out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; + out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; + out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; + out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A ^ EK[16*ROUNDS+0]; out[1] = B + EK[16*ROUNDS+1]; - out[2] = C + EK[16*ROUNDS+2]; out[3] = D ^ EK[16*ROUNDS+3]; - out[4] = E ^ EK[16*ROUNDS+4]; out[5] = F + EK[16*ROUNDS+5]; - out[6] = G + EK[16*ROUNDS+6]; out[7] = H ^ EK[16*ROUNDS+7]; } /* * SAFER-SK Decryption */ -void SAFER_SK::dec(const byte in[], byte out[]) const +void SAFER_SK::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - byte A = in[0], B = in[1], C = in[2], D = in[3], - E = in[4], F = in[5], G = in[6], H = in[7]; - A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; - D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; - G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; - for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + for(u32bit i = 0; i != blocks; ++i) { - byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; - A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; - A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; - A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; - A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; - C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; - E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; - G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; - A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; - E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + byte A = in[0], B = in[1], C = in[2], D = in[3], + E = in[4], F = in[5], G = in[6], H = in[7]; + + A ^= EK[16*ROUNDS+0]; B -= EK[16*ROUNDS+1]; C -= EK[16*ROUNDS+2]; + D ^= EK[16*ROUNDS+3]; E ^= EK[16*ROUNDS+4]; F -= EK[16*ROUNDS+5]; + G -= EK[16*ROUNDS+6]; H ^= EK[16*ROUNDS+7]; + + for(s32bit j = 16*(ROUNDS-1); j >= 0; j -= 16) + { + byte T = E; E = B; B = C; C = T; T = F; F = D; D = G; G = T; + A -= E; B -= F; C -= G; D -= H; E -= A; F -= B; G -= C; H -= D; + A -= C; E -= G; B -= D; F -= H; C -= A; G -= E; D -= B; H -= F; + A -= B; C -= D; E -= F; G -= H; B -= A; D -= C; F -= E; H -= G; + + A = LOG[A - EK[j+8 ] + 256]; B = EXP[B ^ EK[j+9 ]]; + C = EXP[C ^ EK[j+10]]; D = LOG[D - EK[j+11] + 256]; + E = LOG[E - EK[j+12] + 256]; F = EXP[F ^ EK[j+13]]; + G = EXP[G ^ EK[j+14]]; H = LOG[H - EK[j+15] + 256]; + + A ^= EK[j+0]; B -= EK[j+1]; C -= EK[j+2]; D ^= EK[j+3]; + E ^= EK[j+4]; F -= EK[j+5]; G -= EK[j+6]; H ^= EK[j+7]; + } + + out[0] = A; out[1] = B; out[2] = C; out[3] = D; + out[4] = E; out[5] = F; out[6] = G; out[7] = H; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[0] = A; out[1] = B; out[2] = C; out[3] = D; - out[4] = E; out[5] = F; out[6] = G; out[7] = H; } /* diff --git a/src/block/safer/safer_sk.h b/src/block/safer/safer_sk.h index e52c5837c..4d17bba51 100644 --- a/src/block/safer/safer_sk.h +++ b/src/block/safer/safer_sk.h @@ -18,19 +18,22 @@ namespace Botan { class BOTAN_DLL SAFER_SK : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const; BlockCipher* clone() const; + SAFER_SK(u32bit); private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static const byte EXP[256]; static const byte LOG[512]; static const byte BIAS[208]; static const byte KEY_INDEX[208]; + SecureVector<byte> EK; const u32bit ROUNDS; }; diff --git a/src/block/seed/seed.cpp b/src/block/seed/seed.cpp index b06a7cd77..378be16e4 100644 --- a/src/block/seed/seed.cpp +++ b/src/block/seed/seed.cpp @@ -22,69 +22,81 @@ u32bit SEED::G_FUNC::operator()(u32bit X) const /* * SEED Encryption */ -void SEED::enc(const byte in[], byte out[]) const +void SEED::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[2*j]; - T1 = G(B2 ^ B3 ^ K[2*j+1]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[2*j+2]; - T1 = G(B0 ^ B1 ^ K[2*j+3]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[2*j]; + T1 = G(B2 ^ B3 ^ K[2*j+1]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[2*j+2]; + T1 = G(B0 ^ B1 ^ K[2*j+3]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* * SEED Decryption */ -void SEED::dec(const byte in[], byte out[]) const +void SEED::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_be<u32bit>(in, 0); - u32bit B1 = load_be<u32bit>(in, 1); - u32bit B2 = load_be<u32bit>(in, 2); - u32bit B3 = load_be<u32bit>(in, 3); - - G_FUNC G; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit T0, T1; - - T0 = B2 ^ K[30-2*j]; - T1 = G(B2 ^ B3 ^ K[31-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B1 ^= T1; - B0 ^= T0 + T1; - - T0 = B0 ^ K[28-2*j]; - T1 = G(B0 ^ B1 ^ K[29-2*j]); - T0 = G(T1 + T0); - T1 = G(T1 + T0); - B3 ^= T1; - B2 ^= T0 + T1; + u32bit B0 = load_be<u32bit>(in, 0); + u32bit B1 = load_be<u32bit>(in, 1); + u32bit B2 = load_be<u32bit>(in, 2); + u32bit B3 = load_be<u32bit>(in, 3); + + G_FUNC G; + + for(u32bit j = 0; j != 16; j += 2) + { + u32bit T0, T1; + + T0 = B2 ^ K[30-2*j]; + T1 = G(B2 ^ B3 ^ K[31-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B1 ^= T1; + B0 ^= T0 + T1; + + T0 = B0 ^ K[28-2*j]; + T1 = G(B0 ^ B1 ^ K[29-2*j]); + T0 = G(T1 + T0); + T1 = G(T1 + T0); + B3 ^= T1; + B2 ^= T0 + T1; + } + + store_be(out, B2, B3, B0, B1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - - store_be(out, B2, B3, B0, B1); } /* diff --git a/src/block/seed/seed.h b/src/block/seed/seed.h index 54c25d580..5a5a512e7 100644 --- a/src/block/seed/seed.h +++ b/src/block/seed/seed.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL SEED : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "SEED"; } BlockCipher* clone() const { return new SEED; } + SEED() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); class G_FUNC diff --git a/src/block/serpent/serpent.cpp b/src/block/serpent/serpent.cpp index df7592fea..2fa27308f 100644 --- a/src/block/serpent/serpent.cpp +++ b/src/block/serpent/serpent.cpp @@ -243,93 +243,105 @@ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) /* * Serpent Encryption */ -void Serpent::enc(const byte in[], byte out[]) const +void Serpent::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); - key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent::dec(const byte in[], byte out[]) const +void Serpent::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit B0 = load_le<u32bit>(in, 0); - u32bit B1 = load_le<u32bit>(in, 1); - u32bit B2 = load_le<u32bit>(in, 2); - u32bit B3 = load_le<u32bit>(in, 3); - - key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); - i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); - - store_le(out, B0, B1, B2, B3); + for(u32bit i = 0; i != blocks; ++i) + { + u32bit B0 = load_le<u32bit>(in, 0); + u32bit B1 = load_le<u32bit>(in, 1); + u32bit B2 = load_le<u32bit>(in, 2); + u32bit B3 = load_le<u32bit>(in, 3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + store_le(out, B0, B1, B2, B3); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/serpent/serpent.h b/src/block/serpent/serpent.h index 5b9be257f..d919c3008 100644 --- a/src/block/serpent/serpent.h +++ b/src/block/serpent/serpent.h @@ -18,13 +18,14 @@ namespace Botan { class BOTAN_DLL Serpent : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { round_key.clear(); } std::string name() const { return "Serpent"; } BlockCipher* clone() const { return new Serpent; } Serpent() : BlockCipher(16, 16, 32, 8) {} protected: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 132> round_key; diff --git a/src/block/serpent_ia32/info.txt b/src/block/serpent_ia32/info.txt index 13b171fe9..ea0506299 100644 --- a/src/block/serpent_ia32/info.txt +++ b/src/block/serpent_ia32/info.txt @@ -23,6 +23,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/block/serpent_ia32/serp_ia32.cpp b/src/block/serpent_ia32/serp_ia32.cpp index 37dd4e637..997bec2fc 100644 --- a/src/block/serpent_ia32/serp_ia32.cpp +++ b/src/block/serpent_ia32/serp_ia32.cpp @@ -21,17 +21,27 @@ void botan_serpent_ia32_key_schedule(u32bit[140]); /* * Serpent Encryption */ -void Serpent_IA32::enc(const byte in[], byte out[]) const +void Serpent_IA32::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_encrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_encrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Serpent Decryption */ -void Serpent_IA32::dec(const byte in[], byte out[]) const +void Serpent_IA32::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - botan_serpent_ia32_decrypt(in, out, round_key); + for(u32bit i = 0; i != blocks; ++i) + { + botan_serpent_ia32_decrypt(in, out, round_key); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/serpent_ia32/serp_ia32.h b/src/block/serpent_ia32/serp_ia32.h index 565e9889d..dc6beaf13 100644 --- a/src/block/serpent_ia32/serp_ia32.h +++ b/src/block/serpent_ia32/serp_ia32.h @@ -18,10 +18,11 @@ namespace Botan { class BOTAN_DLL Serpent_IA32 : public Serpent { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + BlockCipher* clone() const { return new Serpent_IA32; } private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); }; diff --git a/src/block/serpent_ia32/serp_ia32_imp.S b/src/block/serpent_ia32/serp_ia32_imp.S index ddfcc7806..9e50f8cdc 100644 --- a/src/block/serpent_ia32/serp_ia32_imp.S +++ b/src/block/serpent_ia32/serp_ia32_imp.S @@ -1,7 +1,9 @@ -/************************************************* -* Serpent Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* Serpent Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> @@ -436,9 +438,9 @@ START_LISTING(serp_ia32.S) XOR(C, ARRAY4(EDI, (4*N+2))) ; \ XOR(D, ARRAY4(EDI, (4*N+3))) ; -/************************************************* -* Serpent Encryption * -*************************************************/ +/* +* Serpent Encryption +*/ START_FUNCTION(botan_serpent_ia32_encrypt) SPILL_REGS() #define PUSHED 4 @@ -507,9 +509,9 @@ START_FUNCTION(botan_serpent_ia32_encrypt) #undef PUSHED END_FUNCTION(botan_serpent_ia32_encrypt) -/************************************************* -* Serpent Decryption * -*************************************************/ +/* +* Serpent Decryption +*/ START_FUNCTION(botan_serpent_ia32_decrypt) SPILL_REGS() #define PUSHED 4 @@ -578,9 +580,9 @@ START_FUNCTION(botan_serpent_ia32_decrypt) #undef PUSHED END_FUNCTION(botan_serpent_ia32_decrypt) -/************************************************* -* Serpent Key Schedule * -*************************************************/ +/* +* Serpent Key Schedule +*/ START_FUNCTION(botan_serpent_ia32_key_schedule) SPILL_REGS() #define PUSHED 4 diff --git a/src/block/serpent_sse2/info.txt b/src/block/serpent_sse2/info.txt new file mode 100644 index 000000000..b00ab6e88 --- /dev/null +++ b/src/block/serpent_sse2/info.txt @@ -0,0 +1,16 @@ +realname "Serpent (SSE2)" + +define SERPENT_SSE2 + +load_on auto + +<add> +serp_sse2.cpp +serp_sse2.h +serp_sse2_sbox.h +</add> + +<requires> +serpent +sse2_eng +</requires> diff --git a/src/block/serpent_sse2/serp_sse2.cpp b/src/block/serpent_sse2/serp_sse2.cpp new file mode 100644 index 000000000..c51bb69ab --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.cpp @@ -0,0 +1,240 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/serp_sse2.h> +#include <botan/serp_sse2_sbox.h> +#include <botan/loadstor.h> +#include <emmintrin.h> + +namespace Botan { + +namespace { + +#define key_xor(round, B0, B1, B2, B3) \ + do { \ + __m128i key = _mm_loadu_si128(keys + round); \ + B0 = _mm_xor_si128(B0, _mm_shuffle_epi32(key, _MM_SHUFFLE(0,0,0,0))); \ + B1 = _mm_xor_si128(B1, _mm_shuffle_epi32(key, _MM_SHUFFLE(1,1,1,1))); \ + B2 = _mm_xor_si128(B2, _mm_shuffle_epi32(key, _MM_SHUFFLE(2,2,2,2))); \ + B3 = _mm_xor_si128(B3, _mm_shuffle_epi32(key, _MM_SHUFFLE(3,3,3,3))); \ + } while(0); + +/* +* Serpent's linear transformations +*/ +#define rotate_left_m128(vec, rot) \ + _mm_or_si128(_mm_slli_epi32(vec, rot), _mm_srli_epi32(vec, 32-rot)) + +#define rotate_right_m128(vec, rot) \ + _mm_or_si128(_mm_srli_epi32(vec, rot), _mm_slli_epi32(vec, 32-rot)) + +#define transform(B0, B1, B2, B3) \ + do { \ + B0 = rotate_left_m128(B0, 13); \ + B2 = rotate_left_m128(B2, 3); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = rotate_left_m128(B1, 1); \ + B3 = rotate_left_m128(B3, 7); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = rotate_left_m128(B0, 5); \ + B2 = rotate_left_m128(B2, 22); \ + } while(0); + +#define i_transform(B0, B1, B2, B3) \ + do { \ + B2 = rotate_right_m128(B2, 22); \ + B0 = rotate_right_m128(B0, 5); \ + B2 = _mm_xor_si128(B2, _mm_xor_si128(B3, _mm_slli_epi32(B1, 7))); \ + B0 = _mm_xor_si128(B0, _mm_xor_si128(B1, B3)); \ + B3 = rotate_right_m128(B3, 7); \ + B1 = rotate_right_m128(B1, 1); \ + B3 = _mm_xor_si128(B3, _mm_xor_si128(B2, _mm_slli_epi32(B0, 3))); \ + B1 = _mm_xor_si128(B1, _mm_xor_si128(B0, B2)); \ + B2 = rotate_right_m128(B2, 3); \ + B0 = rotate_right_m128(B0, 13); \ + } while(0); + +/* +* 4x4 SSE2 integer matrix transpose +*/ +#define transpose(B0, B1, B2, B3) \ + do { \ + __m128i T0 = _mm_unpacklo_epi32(B0, B1); \ + __m128i T1 = _mm_unpacklo_epi32(B2, B3); \ + __m128i T2 = _mm_unpackhi_epi32(B0, B1); \ + __m128i T3 = _mm_unpackhi_epi32(B2, B3); \ + B0 = _mm_unpacklo_epi64(T0, T1); \ + B1 = _mm_unpackhi_epi64(T0, T1); \ + B2 = _mm_unpacklo_epi64(T2, T3); \ + B3 = _mm_unpackhi_epi64(T2, T3); \ + } while(0); + +/* +* SSE2 Serpent Encryption of 4 blocks in parallel +*/ +void serpent_encrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor( 0,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 1,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 2,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 3,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 4,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 5,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 6,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 7,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor( 8,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor( 9,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(10,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(11,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(12,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(13,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(14,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(15,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(16,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(17,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(18,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(19,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(20,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(21,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(22,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(23,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); transform(B0,B1,B2,B3); + + key_xor(24,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(25,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(26,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(27,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(28,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(29,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(30,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3); + key_xor(31,B0,B1,B2,B3); SBoxE8(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +/* +* SSE2 Serpent Decryption of 4 blocks in parallel +*/ +void serpent_decrypt_4(const byte in[64], + byte out[64], + const u32bit keys_32[132]) + { + const __m128i all_ones = _mm_set1_epi8(0xFF); + + const __m128i* keys = (const __m128i*)(keys_32); + __m128i* out_mm = (__m128i*)(out); + __m128i* in_mm = (__m128i*)(in); + + __m128i B0 = _mm_loadu_si128(in_mm); + __m128i B1 = _mm_loadu_si128(in_mm + 1); + __m128i B2 = _mm_loadu_si128(in_mm + 2); + __m128i B3 = _mm_loadu_si128(in_mm + 3); + + transpose(B0, B1, B2, B3); + + key_xor(32,B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3); + + i_transform(B0,B1,B2,B3); SBoxD8(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3); + i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3); + + transpose(B0, B1, B2, B3); + + _mm_storeu_si128(out_mm , B0); + _mm_storeu_si128(out_mm + 1, B1); + _mm_storeu_si128(out_mm + 2, B2); + _mm_storeu_si128(out_mm + 3, B3); + } + +} + +/* +* Serpent Encryption +*/ +void Serpent_SSE2::encrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_encrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::encrypt_n(in, out, blocks); + } + +/* +* Serpent Decryption +*/ +void Serpent_SSE2::decrypt_n(const byte in[], byte out[], u32bit blocks) const + { + while(blocks >= 4) + { + serpent_decrypt_4(in, out, this->round_key); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + + Serpent::decrypt_n(in, out, blocks); + } + +} diff --git a/src/block/serpent_sse2/serp_sse2.h b/src/block/serpent_sse2/serp_sse2.h new file mode 100644 index 000000000..f1e5c2028 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2.h @@ -0,0 +1,29 @@ +/* +* Serpent (SSE2) +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_SERPENT_SSE2_H__ +#define BOTAN_SERPENT_SSE2_H__ + +#include <botan/serpent.h> + +namespace Botan { + +/* +* Serpent +*/ +class BOTAN_DLL Serpent_SSE2 : public Serpent + { + public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + + BlockCipher* clone() const { return new Serpent_SSE2; } + }; + +} + +#endif diff --git a/src/block/serpent_sse2/serp_sse2_sbox.h b/src/block/serpent_sse2/serp_sse2_sbox.h new file mode 100644 index 000000000..40c552e87 --- /dev/null +++ b/src/block/serpent_sse2/serp_sse2_sbox.h @@ -0,0 +1,434 @@ +/* +* Serpent Sboxes in SSE2 form +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef SERPENT_SSE2_SBOXES_H__ +#define SERPENT_SSE2_SBOXES_H__ + +#define SBoxE1(B0, B1, B2, B3) \ + do { \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_or_si128(B3, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE2(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, all_ones); \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_or_si128(B2, B0); \ + B2 = _mm_and_si128(B2, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_and_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B2; \ + B2 = B3; \ + B3 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE3(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_and_si128(B0, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B2 = _mm_xor_si128(B2, B0); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = B3; \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B0 = B2; \ + B2 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE4(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B0; \ + B0 = _mm_or_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_and_si128(B1, B4); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = _mm_and_si128(B4, B0); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B2 = B1; \ + B1 = _mm_or_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE5(B0, B1, B2, B3) \ + do { \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_and_si128(B2, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_or_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxE6(B0, B1, B2, B3) \ + do { \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_xor_si128(B3, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_and_si128(B1, B0); \ + B2 = _mm_xor_si128(B2, B3); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B4 = _mm_xor_si128(B4, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B0 = _mm_xor_si128(B0, B4); \ + B4 = _mm_or_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B0; \ + B0 = B1; \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxE7(B0, B1, B2, B3) \ + do { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B0); \ + B0 = _mm_xor_si128(B0, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B3); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = B4; \ + } while(0); + +#define SBoxE8(B0, B1, B2, B3) \ + do { \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B4); \ + B3 = _mm_and_si128(B3, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B4); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_or_si128(B0, B4); \ + B0 = _mm_xor_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_and_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B4); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B2 = _mm_or_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B3; \ + B3 = B0; \ + B0 = B4; \ + } while(0); + +#define SBoxD1(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, all_ones); \ + __m128i B4 = B1; \ + B1 = _mm_or_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_or_si128(B2, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_xor_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_and_si128(B2, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD2(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B1; \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = _mm_or_si128(B0, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B4); \ + B0 = _mm_or_si128(B0, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B0 = _mm_xor_si128(B0, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B4); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = B0; \ + B0 = B4; \ + B4 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD3(B0, B1, B2, B3) \ + do \ + { \ + B2 = _mm_xor_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + __m128i B4 = B3; \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B4); \ + B4 = _mm_and_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_and_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = _mm_and_si128(B2, B1); \ + B2 = _mm_or_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, all_ones); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_and_si128(B0, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + } while(0); + +#define SBoxD4(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B1); \ + B0 = _mm_xor_si128(B0, B2); \ + B4 = _mm_and_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = _mm_and_si128(B0, B1); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_or_si128(B3, B4); \ + B2 = _mm_xor_si128(B2, B3); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B3 = _mm_and_si128(B3, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_xor_si128(B1, B0); \ + B1 = _mm_or_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, B3); \ + B1 = _mm_xor_si128(B1, B4); \ + B0 = _mm_xor_si128(B0, B1); \ + B4 = B0; \ + B0 = B2; \ + B2 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD5(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B3); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = _mm_or_si128(B1, B3); \ + B1 = _mm_and_si128(B1, B0); \ + B4 = _mm_xor_si128(B4, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B0 = _mm_xor_si128(B0, all_ones); \ + B3 = _mm_xor_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B3); \ + B3 = _mm_and_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B0 = _mm_xor_si128(B0, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B4); \ + B2 = _mm_or_si128(B2, B3); \ + B3 = _mm_xor_si128(B3, B0); \ + B2 = _mm_xor_si128(B2, B1); \ + B1 = B3; \ + B3 = B4; \ + } while(0); + +#define SBoxD6(B0, B1, B2, B3) \ + do \ + { \ + B1 = _mm_xor_si128(B1, all_ones); \ + __m128i B4 = B3; \ + B2 = _mm_xor_si128(B2, B1); \ + B3 = _mm_or_si128(B3, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B2 = _mm_or_si128(B2, B1); \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B2); \ + B1 = _mm_xor_si128(B1, B3); \ + B4 = _mm_xor_si128(B4, B2); \ + B3 = _mm_and_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, all_ones); \ + B3 = _mm_xor_si128(B3, B0); \ + B0 = B1; \ + B1 = B4; \ + B4 = B3; \ + B3 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD7(B0, B1, B2, B3) \ + do \ + { \ + B0 = _mm_xor_si128(B0, B2); \ + __m128i B4 = B2; \ + B2 = _mm_and_si128(B2, B0); \ + B4 = _mm_xor_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B2 = _mm_xor_si128(B2, B3); \ + B4 = _mm_or_si128(B4, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_xor_si128(B4, B1); \ + B1 = _mm_and_si128(B1, B3); \ + B1 = _mm_xor_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B3); \ + B0 = _mm_or_si128(B0, B2); \ + B3 = _mm_xor_si128(B3, B1); \ + B4 = _mm_xor_si128(B4, B0); \ + B0 = B1; \ + B1 = B2; \ + B2 = B4; \ + } while(0); + +#define SBoxD8(B0, B1, B2, B3) \ + do \ + { \ + __m128i B4 = B2; \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_and_si128(B0, B3); \ + B4 = _mm_or_si128(B4, B3); \ + B2 = _mm_xor_si128(B2, all_ones); \ + B3 = _mm_xor_si128(B3, B1); \ + B1 = _mm_or_si128(B1, B0); \ + B0 = _mm_xor_si128(B0, B2); \ + B2 = _mm_and_si128(B2, B4); \ + B3 = _mm_and_si128(B3, B4); \ + B1 = _mm_xor_si128(B1, B2); \ + B2 = _mm_xor_si128(B2, B0); \ + B0 = _mm_or_si128(B0, B2); \ + B4 = _mm_xor_si128(B4, B1); \ + B0 = _mm_xor_si128(B0, B3); \ + B3 = _mm_xor_si128(B3, B4); \ + B4 = _mm_or_si128(B4, B0); \ + B3 = _mm_xor_si128(B3, B2); \ + B4 = _mm_xor_si128(B4, B2); \ + B2 = B1; \ + B1 = B0; \ + B0 = B3; \ + B3 = B4; \ + } while(0); + +#endif diff --git a/src/block/skipjack/skipjack.cpp b/src/block/skipjack/skipjack.cpp index f5ffc861e..6c308c0f8 100644 --- a/src/block/skipjack/skipjack.cpp +++ b/src/block/skipjack/skipjack.cpp @@ -13,51 +13,63 @@ namespace Botan { /* * Skipjack Encryption */ -void Skipjack::enc(const byte in[], byte out[]) const +void Skipjack::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); - step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); - step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); + step_A(W1,W4, 1); step_A(W4,W3, 2); step_A(W3,W2, 3); step_A(W2,W1, 4); + step_A(W1,W4, 5); step_A(W4,W3, 6); step_A(W3,W2, 7); step_A(W2,W1, 8); - step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); - step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); + step_B(W1,W2, 9); step_B(W4,W1,10); step_B(W3,W4,11); step_B(W2,W3,12); + step_B(W1,W2,13); step_B(W4,W1,14); step_B(W3,W4,15); step_B(W2,W3,16); - step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); - step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); + step_A(W1,W4,17); step_A(W4,W3,18); step_A(W3,W2,19); step_A(W2,W1,20); + step_A(W1,W4,21); step_A(W4,W3,22); step_A(W3,W2,23); step_A(W2,W1,24); - step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); - step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); + step_B(W1,W2,25); step_B(W4,W1,26); step_B(W3,W4,27); step_B(W2,W3,28); + step_B(W1,W2,29); step_B(W4,W1,30); step_B(W3,W4,31); step_B(W2,W3,32); - store_le(out, W4, W3, W2, W1); + store_le(out, W4, W3, W2, W1); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Skipjack Decryption */ -void Skipjack::dec(const byte in[], byte out[]) const +void Skipjack::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u16bit W1 = load_le<u16bit>(in, 3); - u16bit W2 = load_le<u16bit>(in, 2); - u16bit W3 = load_le<u16bit>(in, 1); - u16bit W4 = load_le<u16bit>(in, 0); + for(u32bit i = 0; i != blocks; ++i) + { + u16bit W1 = load_le<u16bit>(in, 3); + u16bit W2 = load_le<u16bit>(in, 2); + u16bit W3 = load_le<u16bit>(in, 1); + u16bit W4 = load_le<u16bit>(in, 0); + + step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); + step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); - step_Bi(W2,W3,32); step_Bi(W3,W4,31); step_Bi(W4,W1,30); step_Bi(W1,W2,29); - step_Bi(W2,W3,28); step_Bi(W3,W4,27); step_Bi(W4,W1,26); step_Bi(W1,W2,25); + step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); + step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); - step_Ai(W1,W2,24); step_Ai(W2,W3,23); step_Ai(W3,W4,22); step_Ai(W4,W1,21); - step_Ai(W1,W2,20); step_Ai(W2,W3,19); step_Ai(W3,W4,18); step_Ai(W4,W1,17); + step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); + step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); - step_Bi(W2,W3,16); step_Bi(W3,W4,15); step_Bi(W4,W1,14); step_Bi(W1,W2,13); - step_Bi(W2,W3,12); step_Bi(W3,W4,11); step_Bi(W4,W1,10); step_Bi(W1,W2, 9); + step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); + step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); - step_Ai(W1,W2, 8); step_Ai(W2,W3, 7); step_Ai(W3,W4, 6); step_Ai(W4,W1, 5); - step_Ai(W1,W2, 4); step_Ai(W2,W3, 3); step_Ai(W3,W4, 2); step_Ai(W4,W1, 1); + store_le(out, W4, W3, W2, W1); - store_le(out, W4, W3, W2, W1); + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/skipjack/skipjack.h b/src/block/skipjack/skipjack.h index 231cd9c87..f12032f36 100644 --- a/src/block/skipjack/skipjack.h +++ b/src/block/skipjack/skipjack.h @@ -18,18 +18,21 @@ namespace Botan { class BOTAN_DLL Skipjack : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Skipjack"; } BlockCipher* clone() const { return new Skipjack; } + Skipjack() : BlockCipher(8, 10) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); void step_A(u16bit&, u16bit&, u32bit) const; void step_B(u16bit&, u16bit&, u32bit) const; void step_Ai(u16bit&, u16bit&, u32bit) const; void step_Bi(u16bit&, u16bit&, u32bit) const; + SecureBuffer<byte, 256> FTABLE[10]; }; diff --git a/src/block/square/square.cpp b/src/block/square/square.cpp index cb226542d..fdd47d3b2 100644 --- a/src/block/square/square.cpp +++ b/src/block/square/square.cpp @@ -14,103 +14,123 @@ namespace Botan { /* * Square Encryption */ -void Square::enc(const byte in[], byte out[]) const +void Square::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ - TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; - B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ - TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; - B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ - TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; - B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ - TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ - TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; - T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ - TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; - T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ - TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; - T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ - TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; - B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ - TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; - B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ - TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; - B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ - TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; - B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ - TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TE0[in[ 0] ^ ME[ 0]] ^ TE1[in[ 4] ^ ME[ 4]] ^ + TE2[in[ 8] ^ ME[ 8]] ^ TE3[in[12] ^ ME[12]] ^ EK[0]; + B1 = TE0[in[ 1] ^ ME[ 1]] ^ TE1[in[ 5] ^ ME[ 5]] ^ + TE2[in[ 9] ^ ME[ 9]] ^ TE3[in[13] ^ ME[13]] ^ EK[1]; + B2 = TE0[in[ 2] ^ ME[ 2]] ^ TE1[in[ 6] ^ ME[ 6]] ^ + TE2[in[10] ^ ME[10]] ^ TE3[in[14] ^ ME[14]] ^ EK[2]; + B3 = TE0[in[ 3] ^ ME[ 3]] ^ TE1[in[ 7] ^ ME[ 7]] ^ + TE2[in[11] ^ ME[11]] ^ TE3[in[15] ^ ME[15]] ^ EK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TE0[get_byte(0, B0)] ^ TE1[get_byte(0, B1)] ^ + TE2[get_byte(0, B2)] ^ TE3[get_byte(0, B3)] ^ EK[4*j+0]; + T1 = TE0[get_byte(1, B0)] ^ TE1[get_byte(1, B1)] ^ + TE2[get_byte(1, B2)] ^ TE3[get_byte(1, B3)] ^ EK[4*j+1]; + T2 = TE0[get_byte(2, B0)] ^ TE1[get_byte(2, B1)] ^ + TE2[get_byte(2, B2)] ^ TE3[get_byte(2, B3)] ^ EK[4*j+2]; + T3 = TE0[get_byte(3, B0)] ^ TE1[get_byte(3, B1)] ^ + TE2[get_byte(3, B2)] ^ TE3[get_byte(3, B3)] ^ EK[4*j+3]; + + B0 = TE0[get_byte(0, T0)] ^ TE1[get_byte(0, T1)] ^ + TE2[get_byte(0, T2)] ^ TE3[get_byte(0, T3)] ^ EK[4*j+4]; + B1 = TE0[get_byte(1, T0)] ^ TE1[get_byte(1, T1)] ^ + TE2[get_byte(1, T2)] ^ TE3[get_byte(1, T3)] ^ EK[4*j+5]; + B2 = TE0[get_byte(2, T0)] ^ TE1[get_byte(2, T1)] ^ + TE2[get_byte(2, T2)] ^ TE3[get_byte(2, T3)] ^ EK[4*j+6]; + B3 = TE0[get_byte(3, T0)] ^ TE1[get_byte(3, T1)] ^ + TE2[get_byte(3, T2)] ^ TE3[get_byte(3, T3)] ^ EK[4*j+7]; + } + + out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; + out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; + out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; + out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; + out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; + out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; + out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; + out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; + out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; + out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; + out[10] = SE[get_byte(2, B2)] ^ ME[26]; + out[11] = SE[get_byte(2, B3)] ^ ME[27]; + out[12] = SE[get_byte(3, B0)] ^ ME[28]; + out[13] = SE[get_byte(3, B1)] ^ ME[29]; + out[14] = SE[get_byte(3, B2)] ^ ME[30]; + out[15] = SE[get_byte(3, B3)] ^ ME[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SE[get_byte(0, B0)] ^ ME[16]; - out[ 1] = SE[get_byte(0, B1)] ^ ME[17]; - out[ 2] = SE[get_byte(0, B2)] ^ ME[18]; - out[ 3] = SE[get_byte(0, B3)] ^ ME[19]; - out[ 4] = SE[get_byte(1, B0)] ^ ME[20]; - out[ 5] = SE[get_byte(1, B1)] ^ ME[21]; - out[ 6] = SE[get_byte(1, B2)] ^ ME[22]; - out[ 7] = SE[get_byte(1, B3)] ^ ME[23]; - out[ 8] = SE[get_byte(2, B0)] ^ ME[24]; - out[ 9] = SE[get_byte(2, B1)] ^ ME[25]; - out[10] = SE[get_byte(2, B2)] ^ ME[26]; - out[11] = SE[get_byte(2, B3)] ^ ME[27]; - out[12] = SE[get_byte(3, B0)] ^ ME[28]; - out[13] = SE[get_byte(3, B1)] ^ ME[29]; - out[14] = SE[get_byte(3, B2)] ^ ME[30]; - out[15] = SE[get_byte(3, B3)] ^ ME[31]; } /* * Square Decryption */ -void Square::dec(const byte in[], byte out[]) const +void Square::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit T0, T1, T2, T3, B0, B1, B2, B3; - B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ - TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; - B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ - TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; - B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ - TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; - B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ - TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; - for(u32bit j = 1; j != 7; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ - TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; - T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ - TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; - T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ - TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; - T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ - TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; - B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ - TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; - B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ - TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; - B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ - TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; - B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ - TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + u32bit T0, T1, T2, T3, B0, B1, B2, B3; + + B0 = TD0[in[ 0] ^ MD[ 0]] ^ TD1[in[ 4] ^ MD[ 4]] ^ + TD2[in[ 8] ^ MD[ 8]] ^ TD3[in[12] ^ MD[12]] ^ DK[0]; + B1 = TD0[in[ 1] ^ MD[ 1]] ^ TD1[in[ 5] ^ MD[ 5]] ^ + TD2[in[ 9] ^ MD[ 9]] ^ TD3[in[13] ^ MD[13]] ^ DK[1]; + B2 = TD0[in[ 2] ^ MD[ 2]] ^ TD1[in[ 6] ^ MD[ 6]] ^ + TD2[in[10] ^ MD[10]] ^ TD3[in[14] ^ MD[14]] ^ DK[2]; + B3 = TD0[in[ 3] ^ MD[ 3]] ^ TD1[in[ 7] ^ MD[ 7]] ^ + TD2[in[11] ^ MD[11]] ^ TD3[in[15] ^ MD[15]] ^ DK[3]; + + for(u32bit j = 1; j != 7; j += 2) + { + T0 = TD0[get_byte(0, B0)] ^ TD1[get_byte(0, B1)] ^ + TD2[get_byte(0, B2)] ^ TD3[get_byte(0, B3)] ^ DK[4*j+0]; + T1 = TD0[get_byte(1, B0)] ^ TD1[get_byte(1, B1)] ^ + TD2[get_byte(1, B2)] ^ TD3[get_byte(1, B3)] ^ DK[4*j+1]; + T2 = TD0[get_byte(2, B0)] ^ TD1[get_byte(2, B1)] ^ + TD2[get_byte(2, B2)] ^ TD3[get_byte(2, B3)] ^ DK[4*j+2]; + T3 = TD0[get_byte(3, B0)] ^ TD1[get_byte(3, B1)] ^ + TD2[get_byte(3, B2)] ^ TD3[get_byte(3, B3)] ^ DK[4*j+3]; + + B0 = TD0[get_byte(0, T0)] ^ TD1[get_byte(0, T1)] ^ + TD2[get_byte(0, T2)] ^ TD3[get_byte(0, T3)] ^ DK[4*j+4]; + B1 = TD0[get_byte(1, T0)] ^ TD1[get_byte(1, T1)] ^ + TD2[get_byte(1, T2)] ^ TD3[get_byte(1, T3)] ^ DK[4*j+5]; + B2 = TD0[get_byte(2, T0)] ^ TD1[get_byte(2, T1)] ^ + TD2[get_byte(2, T2)] ^ TD3[get_byte(2, T3)] ^ DK[4*j+6]; + B3 = TD0[get_byte(3, T0)] ^ TD1[get_byte(3, T1)] ^ + TD2[get_byte(3, T2)] ^ TD3[get_byte(3, T3)] ^ DK[4*j+7]; + } + + out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; + out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; + out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; + out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; + out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; + out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; + out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; + out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; + out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; + out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; + out[10] = SD[get_byte(2, B2)] ^ MD[26]; + out[11] = SD[get_byte(2, B3)] ^ MD[27]; + out[12] = SD[get_byte(3, B0)] ^ MD[28]; + out[13] = SD[get_byte(3, B1)] ^ MD[29]; + out[14] = SD[get_byte(3, B2)] ^ MD[30]; + out[15] = SD[get_byte(3, B3)] ^ MD[31]; + + in += BLOCK_SIZE; + out += BLOCK_SIZE; } - out[ 0] = SD[get_byte(0, B0)] ^ MD[16]; - out[ 1] = SD[get_byte(0, B1)] ^ MD[17]; - out[ 2] = SD[get_byte(0, B2)] ^ MD[18]; - out[ 3] = SD[get_byte(0, B3)] ^ MD[19]; - out[ 4] = SD[get_byte(1, B0)] ^ MD[20]; - out[ 5] = SD[get_byte(1, B1)] ^ MD[21]; - out[ 6] = SD[get_byte(1, B2)] ^ MD[22]; - out[ 7] = SD[get_byte(1, B3)] ^ MD[23]; - out[ 8] = SD[get_byte(2, B0)] ^ MD[24]; - out[ 9] = SD[get_byte(2, B1)] ^ MD[25]; - out[10] = SD[get_byte(2, B2)] ^ MD[26]; - out[11] = SD[get_byte(2, B3)] ^ MD[27]; - out[12] = SD[get_byte(3, B0)] ^ MD[28]; - out[13] = SD[get_byte(3, B1)] ^ MD[29]; - out[14] = SD[get_byte(3, B2)] ^ MD[30]; - out[15] = SD[get_byte(3, B3)] ^ MD[31]; } /* diff --git a/src/block/square/square.h b/src/block/square/square.h index 94a1fc370..5d9cfc78c 100644 --- a/src/block/square/square.h +++ b/src/block/square/square.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Square : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Square"; } BlockCipher* clone() const { return new Square; } + Square() : BlockCipher(16, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void transform(u32bit[4]); diff --git a/src/block/tea/tea.cpp b/src/block/tea/tea.cpp index 2b4212d9c..de30858da 100644 --- a/src/block/tea/tea.cpp +++ b/src/block/tea/tea.cpp @@ -13,37 +13,49 @@ namespace Botan { /* * TEA Encryption */ -void TEA::enc(const byte in[], byte out[]) const +void TEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - S += 0x9E3779B9; - L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0; + for(u32bit j = 0; j != 32; ++j) + { + S += 0x9E3779B9; + L += ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + R += ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * TEA Decryption */ -void TEA::dec(const byte in[], byte out[]) const +void TEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - u32bit S = 0xC6EF3720; - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); - L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); - S -= 0x9E3779B9; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + u32bit S = 0xC6EF3720; + for(u32bit j = 0; j != 32; ++j) + { + R -= ((L << 4) + K[2]) ^ (L + S) ^ ((L >> 5) + K[3]); + L -= ((R << 4) + K[0]) ^ (R + S) ^ ((R >> 5) + K[1]); + S -= 0x9E3779B9; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/tea/tea.h b/src/block/tea/tea.h index 8ddf3e330..825a051aa 100644 --- a/src/block/tea/tea.h +++ b/src/block/tea/tea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL TEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { K.clear(); } std::string name() const { return "TEA"; } BlockCipher* clone() const { return new TEA; } + TEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 4> K; }; diff --git a/src/block/twofish/twofish.cpp b/src/block/twofish/twofish.cpp index 9784b00a2..6a482a8f3 100644 --- a/src/block/twofish/twofish.cpp +++ b/src/block/twofish/twofish.cpp @@ -14,91 +14,103 @@ namespace Botan { /* * Twofish Encryption */ -void Twofish::enc(const byte in[], byte out[]) const +void Twofish::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[2*j + 9]; - X += round_key[2*j + 8]; - - C = rotate_right(C ^ X, 1); - D = rotate_left(D, 1) ^ Y; - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[2*j + 11]; - X += round_key[2*j + 10]; - - A = rotate_right(A ^ X, 1); - B = rotate_left(B, 1) ^ Y; - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[0]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[1]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[2]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[3]; - C ^= round_key[4]; - D ^= round_key[5]; - A ^= round_key[6]; - B ^= round_key[7]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[2*j + 9]; + X += round_key[2*j + 8]; + + C = rotate_right(C ^ X, 1); + D = rotate_left(D, 1) ^ Y; + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[2*j + 11]; + X += round_key[2*j + 10]; + + A = rotate_right(A ^ X, 1); + B = rotate_left(B, 1) ^ Y; + } - store_le(out, C, D, A, B); + C ^= round_key[4]; + D ^= round_key[5]; + A ^= round_key[6]; + B ^= round_key[7]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * Twofish Decryption */ -void Twofish::dec(const byte in[], byte out[]) const +void Twofish::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; - u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; - u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; - u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - - for(u32bit j = 0; j != 16; j += 2) + for(u32bit i = 0; i != blocks; ++i) { - u32bit X, Y; - - X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ - SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; - Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ - SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; - X += Y; - Y += X + round_key[39 - 2*j]; - X += round_key[38 - 2*j]; - - C = rotate_left(C, 1) ^ X; - D = rotate_right(D ^ Y, 1); - - X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ - SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; - Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ - SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; - X += Y; - Y += X + round_key[37 - 2*j]; - X += round_key[36 - 2*j]; - - A = rotate_left(A, 1) ^ X; - B = rotate_right(B ^ Y, 1); - } + u32bit A = load_le<u32bit>(in, 0) ^ round_key[4]; + u32bit B = load_le<u32bit>(in, 1) ^ round_key[5]; + u32bit C = load_le<u32bit>(in, 2) ^ round_key[6]; + u32bit D = load_le<u32bit>(in, 3) ^ round_key[7]; - C ^= round_key[0]; - D ^= round_key[1]; - A ^= round_key[2]; - B ^= round_key[3]; + for(u32bit j = 0; j != 16; j += 2) + { + u32bit X, Y; + + X = SBox0[get_byte(3, A)] ^ SBox1[get_byte(2, A)] ^ + SBox2[get_byte(1, A)] ^ SBox3[get_byte(0, A)]; + Y = SBox0[get_byte(0, B)] ^ SBox1[get_byte(3, B)] ^ + SBox2[get_byte(2, B)] ^ SBox3[get_byte(1, B)]; + X += Y; + Y += X + round_key[39 - 2*j]; + X += round_key[38 - 2*j]; + + C = rotate_left(C, 1) ^ X; + D = rotate_right(D ^ Y, 1); + + X = SBox0[get_byte(3, C)] ^ SBox1[get_byte(2, C)] ^ + SBox2[get_byte(1, C)] ^ SBox3[get_byte(0, C)]; + Y = SBox0[get_byte(0, D)] ^ SBox1[get_byte(3, D)] ^ + SBox2[get_byte(2, D)] ^ SBox3[get_byte(1, D)]; + X += Y; + Y += X + round_key[37 - 2*j]; + X += round_key[36 - 2*j]; + + A = rotate_left(A, 1) ^ X; + B = rotate_right(B ^ Y, 1); + } - store_le(out, C, D, A, B); + C ^= round_key[0]; + D ^= round_key[1]; + A ^= round_key[2]; + B ^= round_key[3]; + + store_le(out, C, D, A, B); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/twofish/twofish.h b/src/block/twofish/twofish.h index 0640e32f8..87b9aa626 100644 --- a/src/block/twofish/twofish.h +++ b/src/block/twofish/twofish.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL Twofish : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw(); std::string name() const { return "Twofish"; } BlockCipher* clone() const { return new Twofish; } + Twofish() : BlockCipher(16, 16, 32, 8) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); static void rs_mul(byte[4], byte, u32bit); diff --git a/src/block/xtea/xtea.cpp b/src/block/xtea/xtea.cpp index 5047f6594..77543e1e8 100644 --- a/src/block/xtea/xtea.cpp +++ b/src/block/xtea/xtea.cpp @@ -7,40 +7,51 @@ #include <botan/xtea.h> #include <botan/loadstor.h> -#include <botan/parsing.h> namespace Botan { /* * XTEA Encryption */ -void XTEA::enc(const byte in[], byte out[]) const +void XTEA::encrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; - R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + L += (((R << 4) ^ (R >> 5)) + R) ^ EK[2*j]; + R += (((L << 4) ^ (L >> 5)) + L) ^ EK[2*j+1]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* * XTEA Decryption */ -void XTEA::dec(const byte in[], byte out[]) const +void XTEA::decrypt_n(const byte in[], byte out[], u32bit blocks) const { - u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); - - for(u32bit j = 0; j != 32; ++j) + for(u32bit i = 0; i != blocks; ++i) { - R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; - L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; - } + u32bit L = load_be<u32bit>(in, 0), R = load_be<u32bit>(in, 1); + + for(u32bit j = 0; j != 32; ++j) + { + R -= (((L << 4) ^ (L >> 5)) + L) ^ EK[63 - 2*j]; + L -= (((R << 4) ^ (R >> 5)) + R) ^ EK[62 - 2*j]; + } - store_be(out, L, R); + store_be(out, L, R); + + in += BLOCK_SIZE; + out += BLOCK_SIZE; + } } /* diff --git a/src/block/xtea/xtea.h b/src/block/xtea/xtea.h index d9c6066cb..de265818d 100644 --- a/src/block/xtea/xtea.h +++ b/src/block/xtea/xtea.h @@ -18,13 +18,15 @@ namespace Botan { class BOTAN_DLL XTEA : public BlockCipher { public: + void encrypt_n(const byte in[], byte out[], u32bit blocks) const; + void decrypt_n(const byte in[], byte out[], u32bit blocks) const; + void clear() throw() { EK.clear(); } std::string name() const { return "XTEA"; } BlockCipher* clone() const { return new XTEA; } + XTEA() : BlockCipher(8, 16) {} private: - void enc(const byte[], byte[]) const; - void dec(const byte[], byte[]) const; void key_schedule(const byte[], u32bit); SecureBuffer<u32bit, 64> EK; }; diff --git a/src/build-data/arch/arm b/src/build-data/arch/arm index 73cd02f05..c6be4ad46 100644 --- a/src/build-data/arch/arm +++ b/src/build-data/arch/arm @@ -19,4 +19,5 @@ xscale sa110 -> strongarm110 sa1100 -> strongarm1100 strongarm1110 -> strongarm1100 +armv5tel -> xscale </submodel_aliases> diff --git a/src/build-data/arch/m68k b/src/build-data/arch/m68k index 27f246abc..759a3dac1 100644 --- a/src/build-data/arch/m68k +++ b/src/build-data/arch/m68k @@ -2,6 +2,11 @@ realname "Motorola 680x0" default_submodel 68020 +endian big + +# Except for Coldfire +#unaligned ok + <aliases> 680x0 68k diff --git a/src/build-data/arch/mips32 b/src/build-data/arch/mips32 index a07a0a145..9846c8fb2 100644 --- a/src/build-data/arch/mips32 +++ b/src/build-data/arch/mips32 @@ -4,20 +4,19 @@ default_submodel r3000 <aliases> mips +mipsel # For Debian </aliases> <submodels> -mip32-r3000 -mip32-r6000 +r3000 +r6000 </submodels> <submodel_aliases> -r3k -> mips32-r3000 -r6k -> mips32-r6000 +r3k -> r3000 +r6k -> r6000 -r3000 -> mips32-r3000 -r6000 -> mips32-r6000 - -mipsbe -> mips3000 # For RPM -mipsle -> mips3000 # For RPM +# These are for RPM +mipsbe -> r3000 +mipsle -> r3000 </submodel_aliases> diff --git a/src/build-data/arch/mips64 b/src/build-data/arch/mips64 index 228083848..dbb49d028 100644 --- a/src/build-data/arch/mips64 +++ b/src/build-data/arch/mips64 @@ -3,30 +3,20 @@ realname "MIPS64" default_submodel r4400 <submodels> -mips64-r4000 -mips64-r4100 -mips64-r4300 -mips64-r4400 -mips64-r4600 -mips64-r4560 -mips64-r5000 -mips64-r8000 -mips64-r10000 +r4000 +r4100 +r4300 +r4400 +r4600 +r4560 +r5000 +r8000 +r10000 </submodels> <submodel_aliases> -r4k -> mips64-r4000 -r5k -> mips64-r5000 -r8k -> mips64-r8000 -r10k -> mips64-r10000 - -r4000 -> mips64-r4000 -r4100 -> mips64-r4100 -r4300 -> mips64-r4300 -r4400 -> mips64-r4400 -r4600 -> mips64-r4600 -r4560 -> mips64-r4560 -r5000 -> mips64-r5000 -r8000 -> mips64-r8000 -r10000 -> mips64-r10000 +r4k -> r4000 +r5k -> r5000 +r8k -> r8000 +r10k -> r10000 </submodel_aliases> diff --git a/src/build-data/arch/ppc b/src/build-data/arch/ppc index 16112f389..e2dfa6ea2 100644 --- a/src/build-data/arch/ppc +++ b/src/build-data/arch/ppc @@ -1,6 +1,7 @@ realname "PowerPC" endian big +unaligned ok default_submodel ppc604 diff --git a/src/build-data/arch/s390 b/src/build-data/arch/s390 index 392f51397..312b262c4 100644 --- a/src/build-data/arch/s390 +++ b/src/build-data/arch/s390 @@ -2,6 +2,9 @@ realname "S/390 31-bit" default_submodel s390 +endian big +unaligned ok + <submodels> s390 </submodels> diff --git a/src/build-data/arch/s390x b/src/build-data/arch/s390x index 49fb0bda7..9fe6bd615 100644 --- a/src/build-data/arch/s390x +++ b/src/build-data/arch/s390x @@ -2,6 +2,9 @@ realname "S/390 64-bit" default_submodel s390x +endian big +unaligned ok + <submodels> s390x </submodels> diff --git a/src/build-data/botan.doxy.in b/src/build-data/botan.doxy.in index 2da5e1244..87d6e58eb 100644 --- a/src/build-data/botan.doxy.in +++ b/src/build-data/botan.doxy.in @@ -97,7 +97,7 @@ FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = YES -STRIP_CODE_COMMENTS = YES +STRIP_CODE_COMMENTS = NO REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index e4ab0f44b..bd900d412 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -22,6 +22,12 @@ #define BOTAN_KARAT_SQR_THRESHOLD 32 #define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64 +/* Toggles for parallel block cipher mode processing */ +#define BOTAN_PARALLEL_BLOCKS_ECB 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/gcc b/src/build-data/cc/gcc index bde1e5822..7ab80b6ca 100644 --- a/src/build-data/cc/gcc +++ b/src/build-data/cc/gcc @@ -73,7 +73,6 @@ ppc64 -> "-mcpu=SUBMODEL" ppc # Note that the 'linking' bit means "use this for both compiling *and* linking" <mach_abi_linking> amd64 -> "-m64" -mips32 -> "-mabi=n32" mips64 -> "-mabi=64" s390 -> "-m31" s390x -> "-m64" @@ -84,6 +83,7 @@ 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/open64 b/src/build-data/cc/open64 new file mode 100644 index 000000000..b7c1e9e99 --- /dev/null +++ b/src/build-data/cc/open64 @@ -0,0 +1,30 @@ +realname "Open64" + +binary_name "openCC" + +compile_option "-c " +output_to_option "-o " +add_include_dir_option "-I" +add_lib_dir_option "-L" +add_lib_option "-l" + +lib_opt_flags "-O3 -OPT:alias=TYPED" +check_opt_flags "-O3 -OPT:alias=TYPED" +debug_flags "-g3" +no_debug_flags "-fomit-frame-pointer" +shared_flags "-fPIC" +lang_flags "-ansi -LANG:ansi-for-init-scope=ON" +warning_flags "-Wall -W" + +dll_import_flags "" +dll_export_flags "" + +makefile_style unix + +<so_link_flags> +default -> "$(CXX) -shared -Wl,-soname,$(SONAME)" +</so_link_flags> + +<mach_abi_linking> +amd64 -> "-m64" +</mach_abi_linking> diff --git a/src/build-data/os/dragonfly b/src/build-data/os/dragonfly new file mode 100644 index 000000000..7e3663435 --- /dev/null +++ b/src/build-data/os/dragonfly @@ -0,0 +1,11 @@ +realname "DragonFly" + +os_type unix + +<target_features> +posix_mlock +</target_features> + +<supports_shared> +all +</supports_shared> diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp index 352178fd2..5c2e28c39 100644 --- a/src/cert/cvc/cvc_cert.cpp +++ b/src/cert/cvc/cvc_cert.cpp @@ -58,7 +58,7 @@ void EAC1_1_CVC::force_decode() if(cpi != 0) throw Decoding_Error("EAC1_1 certificate´s cpi was not 0"); - // XXX: PK algos have no notion of EAC encoder/decoder currently + // FIXME: PK algos have no notion of EAC encoder/decoder currently #if 0 ECDSA_PublicKey tmp_pk; std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp index 5b2a2c4d4..aa29d8ee6 100644 --- a/src/cert/cvc/cvc_req.cpp +++ b/src/cert/cvc/cvc_req.cpp @@ -41,7 +41,7 @@ void EAC1_1_Req::force_decode() throw Decoding_Error("EAC1_1 request´s cpi was not 0"); } - // XXX: No EAC support in ECDSA + // FIXME: No EAC support in ECDSA #if 0 ECDSA_PublicKey tmp_pk; std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 47c46ca1c..6a81c40ec 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -86,7 +86,7 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key, std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); -#if 0 +#if 0 // FIXME std::unique_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); #else @@ -224,7 +224,7 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); subj_pk->set_parameter_encoding(ENC_EXPLICIT); -#if 0 +#if 0 // FIXME std::unique_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); #else 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 new file mode 100644 index 000000000..c27bbaffa --- /dev/null +++ b/src/cryptobox/cryptobox.cpp @@ -0,0 +1,146 @@ +/* +* Cryptobox Message Routines +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cryptobox.h> +#include <botan/filters.h> +#include <botan/pipe.h> +#include <botan/serpent.h> +#include <botan/sha2_64.h> +#include <botan/ctr.h> +#include <botan/hmac.h> +#include <botan/pbkdf2.h> +#include <botan/pem.h> +#include <botan/loadstor.h> +#include <botan/mem_ops.h> + +namespace Botan { + +namespace CryptoBox { + +namespace { + +/* +First 24 bits of SHA-256("Botan Cryptobox"), followed by 8 0 bits +for later use as flags, etc if needed +*/ +const u32bit CRYPTOBOX_VERSION_CODE = 0xEFC22400; + +const u32bit VERSION_CODE_LEN = 4; +const u32bit CIPHER_KEY_LEN = 32; +const u32bit CIPHER_IV_LEN = 16; +const u32bit MAC_KEY_LEN = 32; +const u32bit MAC_OUTPUT_LEN = 20; +const u32bit PBKDF_SALT_LEN = 10; +const u32bit PBKDF_ITERATIONS = 8 * 1024; + +const u32bit PBKDF_OUTPUT_LEN = CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN; + +} + +std::string encrypt(const byte input[], u32bit input_len, + const std::string& passphrase, + RandomNumberGenerator& rng) + { + SecureVector<byte> pbkdf_salt(PBKDF_SALT_LEN); + rng.randomize(pbkdf_salt.begin(), pbkdf_salt.size()); + + PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); + pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size()); + pbkdf.set_iterations(PBKDF_ITERATIONS); + + OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase); + + SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN); + SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN); + InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN, + CIPHER_IV_LEN); + + Pipe pipe(new CTR_BE(new Serpent, cipher_key, iv), + new Fork( + 0, + new MAC_Filter(new HMAC(new SHA_512), + mac_key, MAC_OUTPUT_LEN))); + + pipe.process_msg(input, input_len); + + /* + Output format is: + version # (4 bytes) + salt (10 bytes) + mac (20 bytes) + ciphertext + */ + u32bit ciphertext_len = pipe.remaining(0); + + SecureVector<byte> out_buf; + + for(u32bit i = 0; i != VERSION_CODE_LEN; ++i) + out_buf.append(get_byte(i, CRYPTOBOX_VERSION_CODE)); + + out_buf.append(pbkdf_salt.begin(), pbkdf_salt.size()); + + out_buf.grow_to(out_buf.size() + MAC_OUTPUT_LEN + ciphertext_len); + pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN, MAC_OUTPUT_LEN, 1); + pipe.read(out_buf + VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN, + ciphertext_len, 0); + + return PEM_Code::encode(out_buf.begin(), out_buf.size(), + "BOTAN CRYPTOBOX MESSAGE"); + } + +std::string decrypt(const byte input[], u32bit input_len, + const std::string& passphrase) + { + DataSource_Memory input_src(input, input_len); + SecureVector<byte> ciphertext = + PEM_Code::decode_check_label(input_src, + "BOTAN CRYPTOBOX MESSAGE"); + + if(ciphertext.size() < (VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN)) + throw Decoding_Error("Invalid CryptoBox input"); + + for(u32bit i = 0; i != VERSION_CODE_LEN; ++i) + if(ciphertext[i] != get_byte(i, CRYPTOBOX_VERSION_CODE)) + throw Decoding_Error("Bad CryptoBox version"); + + SecureVector<byte> pbkdf_salt(ciphertext + VERSION_CODE_LEN, PBKDF_SALT_LEN); + + PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512)); + pbkdf.change_salt(pbkdf_salt.begin(), pbkdf_salt.size()); + pbkdf.set_iterations(PBKDF_ITERATIONS); + + OctetString mk = pbkdf.derive_key(PBKDF_OUTPUT_LEN, passphrase); + + SymmetricKey cipher_key(mk.begin(), CIPHER_KEY_LEN); + SymmetricKey mac_key(mk.begin() + CIPHER_KEY_LEN, MAC_KEY_LEN); + InitializationVector iv(mk.begin() + CIPHER_KEY_LEN + MAC_KEY_LEN, + CIPHER_IV_LEN); + + Pipe pipe(new Fork( + new CTR_BE(new Serpent, cipher_key, iv), + new MAC_Filter(new HMAC(new SHA_512), + mac_key, MAC_OUTPUT_LEN))); + + const u32bit ciphertext_offset = + VERSION_CODE_LEN + PBKDF_SALT_LEN + MAC_OUTPUT_LEN; + + pipe.process_msg(ciphertext + ciphertext_offset, + ciphertext.size() - ciphertext_offset); + + byte computed_mac[MAC_OUTPUT_LEN]; + pipe.read(computed_mac, MAC_OUTPUT_LEN, 1); + + if(!same_mem(computed_mac, ciphertext + VERSION_CODE_LEN + PBKDF_SALT_LEN, + MAC_OUTPUT_LEN)) + throw Integrity_Failure("CryptoBox integrity failure"); + + return pipe.read_all_as_string(0); + } + +} + +} diff --git a/src/cryptobox/cryptobox.h b/src/cryptobox/cryptobox.h new file mode 100644 index 000000000..a30cb244a --- /dev/null +++ b/src/cryptobox/cryptobox.h @@ -0,0 +1,42 @@ +/* +* Cryptobox Message Routines +* (C) 2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_CRYPTOBOX_H__ +#define BOTAN_CRYPTOBOX_H__ + +#include <string> +#include <botan/rng.h> + +namespace Botan { + +namespace CryptoBox { + +/** +* Encrypt a message +* @param input the input data +* @param input_len the length of input in bytes +* @param passphrase the passphrase used to encrypt the message +* @param rng a ref to a random number generator, such as AutoSeeded_RNG +*/ +BOTAN_DLL std::string encrypt(const byte input[], u32bit input_len, + const std::string& passphrase, + RandomNumberGenerator& rng); + +/** +* Decrypt a message encrypted with CryptoBox::encrypt +* @param input the input data +* @param input_len the length of input in bytes +* @param passphrase the passphrase used to encrypt the message +*/ +BOTAN_DLL std::string decrypt(const byte input[], u32bit input_len, + const std::string& passphrase); + +} + +} + +#endif diff --git a/src/cryptobox/info.txt b/src/cryptobox/info.txt new file mode 100644 index 000000000..b9b98060f --- /dev/null +++ b/src/cryptobox/info.txt @@ -0,0 +1,22 @@ +realname "Crypto Box" + +load_on auto + +define CRYPTO_BOX + +<add> +cryptobox.h +cryptobox.cpp +</add> + +<requires> +filters +ctr +hmac +rng +serpent +sha2 +base64 +pbkdf2 +pem +</requires> diff --git a/src/engine/openssl/ossl_md.cpp b/src/engine/openssl/ossl_md.cpp index 08672cfc8..7c8fb678c 100644 --- a/src/engine/openssl/ossl_md.cpp +++ b/src/engine/openssl/ossl_md.cpp @@ -95,20 +95,30 @@ EVP_HashFunction::~EVP_HashFunction() HashFunction* OpenSSL_Engine::find_hash(const SCAN_Name& request, Algorithm_Factory&) const { +#ifndef OPENSSL_NO_SHA if(request.algo_name() == "SHA-160") return new EVP_HashFunction(EVP_sha1(), "SHA-160"); +#endif +#ifndef OPENSSL_NO_MD2 if(request.algo_name() == "MD2") return new EVP_HashFunction(EVP_md2(), "MD2"); +#endif +#ifndef OPENSSL_NO_MD4 if(request.algo_name() == "MD4") return new EVP_HashFunction(EVP_md4(), "MD4"); +#endif +#ifndef OPENSSL_NO_MD5 if(request.algo_name() == "MD5") return new EVP_HashFunction(EVP_md5(), "MD5"); +#endif +#ifndef OPENSSL_NO_RIPEMD if(request.algo_name() == "RIPEMD-160") return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160"); +#endif return 0; } diff --git a/src/engine/sse2_eng/eng_sse2.cpp b/src/engine/sse2_eng/eng_sse2.cpp index c738b3d96..9f68a070e 100644 --- a/src/engine/sse2_eng/eng_sse2.cpp +++ b/src/engine/sse2_eng/eng_sse2.cpp @@ -1,6 +1,6 @@ /** * SSE2 Assembly Engine -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,10 +11,27 @@ #include <botan/sha1_sse2.h> #endif +#if defined(BOTAN_HAS_SERPENT_SSE2) + #include <botan/serp_sse2.h> +#endif + namespace Botan { -HashFunction* SSE2_Assembler_Engine::find_hash(const SCAN_Name& request, - Algorithm_Factory&) const +BlockCipher* +SSE2_Assembler_Engine::find_block_cipher(const SCAN_Name& request, + Algorithm_Factory&) const + { +#if defined(BOTAN_HAS_SERPENT_SSE2) + if(request.algo_name() == "Serpent") + return new Serpent_SSE2; +#endif + + return 0; + } + +HashFunction* +SSE2_Assembler_Engine::find_hash(const SCAN_Name& request, + Algorithm_Factory&) const { #if defined(BOTAN_HAS_SHA1_SSE2) if(request.algo_name() == "SHA-160") diff --git a/src/engine/sse2_eng/eng_sse2.h b/src/engine/sse2_eng/eng_sse2.h index 129697e8f..c6b0ce889 100644 --- a/src/engine/sse2_eng/eng_sse2.h +++ b/src/engine/sse2_eng/eng_sse2.h @@ -1,6 +1,6 @@ /** * SSE2 Assembly Engine -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -17,6 +17,9 @@ class BOTAN_DLL SSE2_Assembler_Engine : public Engine public: std::string provider_name() const { return "sse2"; } private: + BlockCipher* find_block_cipher(const SCAN_Name&, + Algorithm_Factory&) const; + HashFunction* find_hash(const SCAN_Name& reqeust, Algorithm_Factory&) const; }; diff --git a/src/engine/sse2_eng/info.txt b/src/engine/sse2_eng/info.txt index 6242c7fee..7595b8eb5 100644 --- a/src/engine/sse2_eng/info.txt +++ b/src/engine/sse2_eng/info.txt @@ -10,6 +10,13 @@ eng_sse2.h </add> <arch> -ia32 +pentium-m +pentium4 +prescott amd64 </arch> + +<cc> +gcc +icc +</cc> diff --git a/src/entropy/dev_random/info.txt b/src/entropy/dev_random/info.txt index 6622886af..fddb7ac06 100644 --- a/src/entropy/dev_random/info.txt +++ b/src/entropy/dev_random/info.txt @@ -16,6 +16,7 @@ beos cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/src/entropy/egd/es_egd.cpp b/src/entropy/egd/es_egd.cpp index a2e3d3791..9e37f8f17 100644 --- a/src/entropy/egd/es_egd.cpp +++ b/src/entropy/egd/es_egd.cpp @@ -98,7 +98,7 @@ u32bit EGD_EntropySource::EGD_Socket::read(byte outbuf[], u32bit length) return static_cast<u32bit>(count); } - catch(std::exception& e) + catch(std::exception) { this->close(); // Will attempt to reopen next poll diff --git a/src/entropy/egd/info.txt b/src/entropy/egd/info.txt index 6b34f395c..85ba86c00 100644 --- a/src/entropy/egd/info.txt +++ b/src/entropy/egd/info.txt @@ -20,6 +20,7 @@ aix cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/src/entropy/proc_walk/es_ftw.cpp b/src/entropy/proc_walk/es_ftw.cpp index fe9dfec38..2016f099a 100644 --- a/src/entropy/proc_walk/es_ftw.cpp +++ b/src/entropy/proc_walk/es_ftw.cpp @@ -81,7 +81,7 @@ int Directory_Walker::next_fd() if(S_ISDIR(stat_buf.st_mode)) add_directory(full_path); - else if(S_ISREG(stat_buf.st_mode)) + else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH)) { int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY); @@ -118,7 +118,7 @@ void FTW_EntropySource::poll(Entropy_Accumulator& accum) if(!dir) dir = new Directory_Walker(path); - MemoryRegion<byte>& io_buffer = accum.get_io_buffer(2048); + MemoryRegion<byte>& io_buffer = accum.get_io_buffer(128); for(u32bit i = 0; i != MAX_FILES_READ_PER_POLL; ++i) { diff --git a/src/entropy/proc_walk/info.txt b/src/entropy/proc_walk/info.txt index 9f4836458..db96ccdb8 100644 --- a/src/entropy/proc_walk/info.txt +++ b/src/entropy/proc_walk/info.txt @@ -15,6 +15,7 @@ aix cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/src/filters/algo_filt.cpp b/src/filters/algo_filt.cpp index 23f7a20cf..3268276a6 100644 --- a/src/filters/algo_filt.cpp +++ b/src/filters/algo_filt.cpp @@ -18,7 +18,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = cipher = af.make_stream_cipher(sc_name); + cipher = af.make_stream_cipher(sc_name); } /* @@ -27,7 +27,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name) : StreamCipher_Filter::StreamCipher_Filter(StreamCipher* stream_cipher) : buffer(DEFAULT_BUFFERSIZE) { - base_ptr = cipher = stream_cipher; + cipher = stream_cipher; } /* @@ -38,7 +38,7 @@ StreamCipher_Filter::StreamCipher_Filter(const std::string& sc_name, buffer(DEFAULT_BUFFERSIZE) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = cipher = af.make_stream_cipher(sc_name); + cipher = af.make_stream_cipher(sc_name); cipher->set_key(key); } @@ -95,7 +95,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, u32bit len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = mac = af.make_mac(mac_name); + mac = af.make_mac(mac_name); } /* @@ -105,7 +105,7 @@ MAC_Filter::MAC_Filter(const std::string& mac_name, const SymmetricKey& key, u32bit len) : OUTPUT_LENGTH(len) { Algorithm_Factory& af = global_state().algorithm_factory(); - base_ptr = mac = af.make_mac(mac_name); + mac = af.make_mac(mac_name); mac->set_key(key); } diff --git a/src/filters/basefilt.cpp b/src/filters/basefilt.cpp index 02dbd8a73..c91a5aa62 100644 --- a/src/filters/basefilt.cpp +++ b/src/filters/basefilt.cpp @@ -50,25 +50,4 @@ Fork::Fork(Filter* filters[], u32bit count) set_next(filters, count); } -/* -* Set the algorithm key -*/ -void Keyed_Filter::set_key(const SymmetricKey& key) - { - if(base_ptr) - base_ptr->set_key(key); - else - throw Invalid_State("Keyed_Filter::set_key: No base algorithm set"); - } - -/* -* Check if a keylength is valid -*/ -bool Keyed_Filter::valid_keylength(u32bit n) const - { - if(base_ptr) - return base_ptr->valid_keylength(n); - throw Invalid_State("Keyed_Filter::valid_keylength: No base algorithm set"); - } - } diff --git a/src/filters/basefilt.h b/src/filters/basefilt.h index 75625abb0..348ad6fd3 100644 --- a/src/filters/basefilt.h +++ b/src/filters/basefilt.h @@ -9,7 +9,6 @@ #define BOTAN_BASEFILT_H__ #include <botan/filter.h> -#include <botan/sym_algo.h> namespace Botan { @@ -62,38 +61,6 @@ class BOTAN_DLL Fork : public Fanout_Filter Fork(Filter* filter_arr[], u32bit length); }; -/** -* This class represents keyed filters, i.e. filters that have to be -* fed with a key in order to function. -*/ -class BOTAN_DLL Keyed_Filter : public Filter - { - public: - - /** - * Set the key of this filter. - * @param key the key to set - */ - virtual void set_key(const SymmetricKey& key); - - /** - * Set the initialization vector of this filter. - * @param iv the initialization vector to set - */ - virtual void set_iv(const InitializationVector&) {} - - /** - * Check whether a key length is valid for this filter. - * @param length the key length to be checked for validity - * @return true if the key length is valid, false otherwise - */ - virtual bool valid_keylength(u32bit length) const; - - Keyed_Filter() { base_ptr = 0; } - protected: - SymmetricAlgorithm* base_ptr; - }; - } #endif diff --git a/src/filters/fd_unix/info.txt b/src/filters/fd_unix/info.txt index e1f30ea28..d87978cb0 100644 --- a/src/filters/fd_unix/info.txt +++ b/src/filters/fd_unix/info.txt @@ -16,6 +16,7 @@ beos cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/src/filters/filters.h b/src/filters/filters.h index 725651f7d..964be0bd8 100644 --- a/src/filters/filters.h +++ b/src/filters/filters.h @@ -15,7 +15,9 @@ #include <botan/pipe.h> #include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/data_snk.h> + #include <botan/scan_name.h> #if defined(BOTAN_HAS_BASE64_CODEC) @@ -36,6 +38,13 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter public: /** + * Write input data + * @param input data + * @param input_len length of input in bytes + */ + void write(const byte input[], u32bit input_len); + + /** * Seek in the stream. * @param position the position to seek ahead */ @@ -53,7 +62,20 @@ class BOTAN_DLL StreamCipher_Filter : public Keyed_Filter * @param iv the initialization vector to set */ void set_iv(const InitializationVector& iv); - void write(const byte[], u32bit); + + /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + bool valid_keylength(u32bit length) const + { return cipher->valid_keylength(length); } /** * Construct a stream cipher filter. @@ -126,6 +148,20 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter void end_msg(); /** + * Set the key of this filter. + * @param key the key to set + */ + void set_key(const SymmetricKey& key) { mac->set_key(key); } + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + bool valid_keylength(u32bit length) const + { return mac->valid_keylength(length); } + + /** * Construct a MAC filter. The MAC key will be left empty. * @param mac the MAC to use * @param len the output length of this filter. Leave the default @@ -136,7 +172,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter MAC_Filter(MessageAuthenticationCode* mac_obj, u32bit out_len = 0) : OUTPUT_LENGTH(out_len) { - base_ptr = mac = mac_obj; + mac = mac_obj; } /** @@ -152,7 +188,7 @@ class BOTAN_DLL MAC_Filter : public Keyed_Filter const SymmetricKey& key, u32bit out_len = 0) : OUTPUT_LENGTH(out_len) { - base_ptr = mac = mac_obj; + mac = mac_obj; mac->set_key(key); } diff --git a/src/filters/info.txt b/src/filters/info.txt index 79a92a9c5..fb8108659 100644 --- a/src/filters/info.txt +++ b/src/filters/info.txt @@ -17,6 +17,7 @@ data_src.h filter.cpp filter.h filters.h +key_filt.h out_buf.cpp out_buf.h pbe.h diff --git a/src/filters/key_filt.h b/src/filters/key_filt.h new file mode 100644 index 000000000..36af91f88 --- /dev/null +++ b/src/filters/key_filt.h @@ -0,0 +1,45 @@ +/* +* Keyed_Filter +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_KEYED_FILTER_H__ +#define BOTAN_KEYED_FILTER_H__ + +#include <botan/filter.h> +#include <botan/sym_algo.h> + +namespace Botan { + +/** +* This class represents keyed filters, i.e. filters that have to be +* fed with a key in order to function. +*/ +class BOTAN_DLL Keyed_Filter : public Filter + { + public: + /** + * Set the key of this filter. + * @param key the key to set + */ + virtual void set_key(const SymmetricKey& key) = 0; + + /** + * Set the initialization vector of this filter. + * @param iv the initialization vector to set + */ + virtual void set_iv(const InitializationVector&) {} + + /** + * Check whether a key length is valid for this filter. + * @param length the key length to be checked for validity + * @return true if the key length is valid, false otherwise + */ + virtual bool valid_keylength(u32bit length) const = 0; + }; + +} + +#endif diff --git a/src/hash/md4_ia32/info.txt b/src/hash/md4_ia32/info.txt index e5287dc5d..fee7dd1a8 100644 --- a/src/hash/md4_ia32/info.txt +++ b/src/hash/md4_ia32/info.txt @@ -23,6 +23,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/hash/md4_ia32/md4_ia32_imp.S b/src/hash/md4_ia32/md4_ia32_imp.S index 9b728c73d..ca04cbe4e 100644 --- a/src/hash/md4_ia32/md4_ia32_imp.S +++ b/src/hash/md4_ia32/md4_ia32_imp.S @@ -1,7 +1,9 @@ -/************************************************* -* MD4 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* MD4 Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/hash/md5_ia32/info.txt b/src/hash/md5_ia32/info.txt index f69ab82e6..ad9923b26 100644 --- a/src/hash/md5_ia32/info.txt +++ b/src/hash/md5_ia32/info.txt @@ -23,6 +23,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/hash/md5_ia32/md5_ia32_imp.S b/src/hash/md5_ia32/md5_ia32_imp.S index 7f9268a1e..8087bbdbc 100644 --- a/src/hash/md5_ia32/md5_ia32_imp.S +++ b/src/hash/md5_ia32/md5_ia32_imp.S @@ -1,7 +1,9 @@ -/************************************************* -* MD5 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* MD5 Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/hash/sha1_amd64/sha1_amd64_imp.S b/src/hash/sha1_amd64/sha1_amd64_imp.S index f20494999..34a8318ed 100644 --- a/src/hash/sha1_amd64/sha1_amd64_imp.S +++ b/src/hash/sha1_amd64/sha1_amd64_imp.S @@ -1,7 +1,9 @@ -/************************************************* -* SHA-160 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* SHA-160 Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/hash/sha1_ia32/info.txt b/src/hash/sha1_ia32/info.txt index ca14028b8..bfb321145 100644 --- a/src/hash/sha1_ia32/info.txt +++ b/src/hash/sha1_ia32/info.txt @@ -23,6 +23,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/hash/sha1_ia32/sha1_ia32_imp.S b/src/hash/sha1_ia32/sha1_ia32_imp.S index b7f881383..e76b9fb76 100644 --- a/src/hash/sha1_ia32/sha1_ia32_imp.S +++ b/src/hash/sha1_ia32/sha1_ia32_imp.S @@ -1,7 +1,9 @@ -/************************************************* -* SHA-160 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* SHA-160 Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/hash/sha1_sse2/info.txt b/src/hash/sha1_sse2/info.txt index b8d693b70..995c2513e 100644 --- a/src/hash/sha1_sse2/info.txt +++ b/src/hash/sha1_sse2/info.txt @@ -10,18 +10,6 @@ sha1_sse2.cpp sha1_sse2.h </add> -<arch> -pentium-m -pentium4 -prescott -amd64 -</arch> - -<cc> -gcc -icc -</cc> - <requires> sha1 sse2_eng diff --git a/src/libstate/info.txt b/src/libstate/info.txt index 7ca35c5a4..6eaa2f70b 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -1,6 +1,6 @@ realname "Botan Libstate Module" -load_on auto +load_on always define LIBSTATE_MODULE diff --git a/src/libstate/pk_engine.h b/src/libstate/pk_engine.h index 3f8650a4e..256a47c20 100644 --- a/src/libstate/pk_engine.h +++ b/src/libstate/pk_engine.h @@ -9,6 +9,7 @@ #define BOTAN_ENGINE_PK_LOOKUP_H__ #include <botan/bigint.h> +#include <botan/pow_mod.h> #if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) #include <botan/if_op.h> diff --git a/src/libstate/scan_name.cpp b/src/libstate/scan_name.cpp index 4ca6e6d59..889ef7367 100644 --- a/src/libstate/scan_name.cpp +++ b/src/libstate/scan_name.cpp @@ -1,6 +1,6 @@ /** -SCAN Name Abstraction -(C) 2008 Jack Lloyd +* SCAN Name Abstraction +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/libstate/scan_name.h b/src/libstate/scan_name.h index 9e7af40d6..b3f2004e2 100644 --- a/src/libstate/scan_name.h +++ b/src/libstate/scan_name.h @@ -1,6 +1,6 @@ /** -SCAN Name Abstraction -(C) 2008 Jack Lloyd +* SCAN Name Abstraction +* (C) 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/mac/mac.cpp b/src/mac/mac.cpp index 96df25503..04b259647 100644 --- a/src/mac/mac.cpp +++ b/src/mac/mac.cpp @@ -1,6 +1,6 @@ /** -Message Authentication Code base class -(C) 1999-2008 Jack Lloyd +* Message Authentication Code base class +* (C) 1999-2008 Jack Lloyd * * Distributed under the terms of the Botan license */ diff --git a/src/math/bigint/monty_amd64/info.txt b/src/math/bigint/monty_amd64/info.txt index 7fb70da46..a897045b2 100644 --- a/src/math/bigint/monty_amd64/info.txt +++ b/src/math/bigint/monty_amd64/info.txt @@ -21,6 +21,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/math/bigint/monty_amd64/mp_monty.S b/src/math/bigint/monty_amd64/mp_monty.S index 3dd4040bc..22045c369 100644 --- a/src/math/bigint/monty_amd64/mp_monty.S +++ b/src/math/bigint/monty_amd64/mp_monty.S @@ -1,7 +1,9 @@ -/************************************************* -* Montgomery Reduction Source File * -* (C) 2008 Jack Lloyd * -*************************************************/ +/* +* Montgomery Reduction Source File +* (C) 2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/math/bigint/mp_asm64/mp_asm.h b/src/math/bigint/mp_asm64/mp_asm.h index d1583e236..c9159eaa7 100644 --- a/src/math/bigint/mp_asm64/mp_asm.h +++ b/src/math/bigint/mp_asm64/mp_asm.h @@ -57,7 +57,7 @@ namespace Botan { // with 64-bit registers/ALU, but no 64x64->128 multiply. inline void bigint_2word_mul(word a, word b, word* z1, word* z0) { - const u32bit MP_HWORD_BITS = MP_WORD_BITS / 2; + const u32bit MP_HWORD_BITS = BOTAN_MP_WORD_BITS / 2; const word MP_HWORD_MASK = ((word)1 << MP_HWORD_BITS) - 1; const word a_hi = (a >> MP_HWORD_BITS); diff --git a/src/math/bigint/mulop_amd64/info.txt b/src/math/bigint/mulop_amd64/info.txt index c4b14db93..77990df80 100644 --- a/src/math/bigint/mulop_amd64/info.txt +++ b/src/math/bigint/mulop_amd64/info.txt @@ -21,6 +21,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/math/bigint/mulop_amd64/mp_mulop_amd64.S b/src/math/bigint/mulop_amd64/mp_mulop_amd64.S index e5bba23fb..63ac55e95 100644 --- a/src/math/bigint/mulop_amd64/mp_mulop_amd64.S +++ b/src/math/bigint/mulop_amd64/mp_mulop_amd64.S @@ -1,7 +1,9 @@ -/************************************************* -* Simple O(N^2) Multiplication and Squaring * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ +/* +* Simple O(N^2) Multiplication and Squaring +* (C) 1999-2008 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/math/bigint/mulop_ia32/info.txt b/src/math/bigint/mulop_ia32/info.txt index a7b525bfb..b995dd8d7 100644 --- a/src/math/bigint/mulop_ia32/info.txt +++ b/src/math/bigint/mulop_ia32/info.txt @@ -23,6 +23,7 @@ icc <os> linux freebsd +dragonfly netbsd openbsd solaris diff --git a/src/math/bigint/mulop_ia32/mp_mulop.S b/src/math/bigint/mulop_ia32/mp_mulop.S index a5f0d3b27..716166fd9 100644 --- a/src/math/bigint/mulop_ia32/mp_mulop.S +++ b/src/math/bigint/mulop_ia32/mp_mulop.S @@ -1,7 +1,9 @@ -/************************************************* -* Multiply/Add Algorithm Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* Multiply/Add Algorithm Source File +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/asm_macr.h> diff --git a/src/modes/ctr/ctr.cpp b/src/modes/ctr/ctr.cpp index 9eb42ec5a..d458d7848 100644 --- a/src/modes/ctr/ctr.cpp +++ b/src/modes/ctr/ctr.cpp @@ -1,6 +1,6 @@ /* * CTR Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,12 +11,21 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_CTR; + +} + /* * CTR-BE Constructor */ -CTR_BE::CTR_BE(BlockCipher* ciph) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) +CTR_BE::CTR_BE(BlockCipher* ciph) : cipher(ciph) { + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); } /* @@ -24,39 +33,88 @@ CTR_BE::CTR_BE(BlockCipher* ciph) : */ CTR_BE::CTR_BE(BlockCipher* ciph, const SymmetricKey& key, const InitializationVector& iv) : - BlockCipherMode(ciph, "CTR-BE", ciph->BLOCK_SIZE, 1) + cipher(ciph) { - set_key(key); + position = 0; + + counter.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + enc_buffer.create(ciph->BLOCK_SIZE * PARALLEL_BLOCKS); + + cipher->set_key(key); set_iv(iv); } /* +* CTR_BE Destructor +*/ +CTR_BE::~CTR_BE() + { + delete cipher; + } + +/* +* Return the name of this type +*/ +std::string CTR_BE::name() const + { + return ("CTR-BE/" + cipher->name()); + } + +/* +* Set CTR-BE IV +*/ +void CTR_BE::set_iv(const InitializationVector& iv) + { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(iv.length() != BLOCK_SIZE) + throw Invalid_IV_Length(name(), iv.length()); + + enc_buffer.clear(); + position = 0; + + counter.copy(0, iv.begin(), iv.length()); + + for(u32bit i = 1; i != PARALLEL_BLOCKS; ++i) + { + counter.copy(i*BLOCK_SIZE, + counter.begin() + (i-1)*BLOCK_SIZE, BLOCK_SIZE); + + for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) + if(++counter[i*BLOCK_SIZE+j]) + break; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + } + +/* * CTR-BE Encryption/Decryption */ void CTR_BE::write(const byte input[], u32bit length) { - u32bit copied = std::min(BLOCK_SIZE - position, length); - xor_buf(buffer + position, input, copied); - send(buffer + position, copied); + u32bit copied = std::min(enc_buffer.size() - position, length); + xor_buf(enc_buffer + position, input, copied); + send(enc_buffer + position, copied); input += copied; length -= copied; position += copied; - if(position == BLOCK_SIZE) + if(position == enc_buffer.size()) increment_counter(); - while(length >= BLOCK_SIZE) + while(length >= enc_buffer.size()) { - xor_buf(buffer, input, BLOCK_SIZE); - send(buffer, BLOCK_SIZE); + xor_buf(enc_buffer, input, enc_buffer.size()); + send(enc_buffer, enc_buffer.size()); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + input += enc_buffer.size(); + length -= enc_buffer.size(); increment_counter(); } - xor_buf(buffer + position, input, length); - send(buffer + position, length); + xor_buf(enc_buffer + position, input, length); + send(enc_buffer + position, length); position += length; } @@ -65,10 +123,23 @@ void CTR_BE::write(const byte input[], u32bit length) */ void CTR_BE::increment_counter() { - for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j) - if(++state[j]) - break; - cipher->encrypt(state, buffer); + for(u32bit i = 0; i != PARALLEL_BLOCKS; ++i) + { + byte* this_ctr = counter + i*cipher->BLOCK_SIZE; + + byte last_byte = this_ctr[cipher->BLOCK_SIZE-1]; + last_byte += PARALLEL_BLOCKS; + + if(this_ctr[cipher->BLOCK_SIZE-1] > last_byte) + for(s32bit j = cipher->BLOCK_SIZE - 2; j >= 0; --j) + if(++this_ctr[j]) + break; + + this_ctr[cipher->BLOCK_SIZE-1] = last_byte; + } + + cipher->encrypt_n(counter, enc_buffer, PARALLEL_BLOCKS); + position = 0; } diff --git a/src/modes/ctr/ctr.h b/src/modes/ctr/ctr.h index aa0db5761..1948ffe48 100644 --- a/src/modes/ctr/ctr.h +++ b/src/modes/ctr/ctr.h @@ -8,22 +8,37 @@ #ifndef BOTAN_COUNTER_MODE_H__ #define BOTAN_COUNTER_MODE_H__ -#include <botan/modebase.h> -#include <botan/modebase.h> +#include <botan/key_filt.h> +#include <botan/block_cipher.h> namespace Botan { /* * CTR-BE Mode */ -class BOTAN_DLL CTR_BE : public BlockCipherMode +class BOTAN_DLL CTR_BE : public Keyed_Filter { public: + std::string name() const; + + void set_iv(const InitializationVector&); + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + CTR_BE(BlockCipher*); CTR_BE(BlockCipher*, const SymmetricKey&, const InitializationVector&); + + ~CTR_BE(); private: void write(const byte[], u32bit); void increment_counter(); + + BlockCipher* cipher; + SecureVector<byte> counter, enc_buffer; + u32bit position; }; } diff --git a/src/modes/eax/eax.h b/src/modes/eax/eax.h index 1bb2e510d..f569f2ede 100644 --- a/src/modes/eax/eax.h +++ b/src/modes/eax/eax.h @@ -8,7 +8,7 @@ #ifndef BOTAN_EAX_H__ #define BOTAN_EAX_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> #include <botan/mac.h> diff --git a/src/modes/ecb/ecb.cpp b/src/modes/ecb/ecb.cpp index 8da0a4802..988a8b3f2 100644 --- a/src/modes/ecb/ecb.cpp +++ b/src/modes/ecb/ecb.cpp @@ -9,22 +9,60 @@ namespace Botan { +namespace { + +const u32bit PARALLEL_BLOCKS = BOTAN_PARALLEL_BLOCKS_ECB; + +} + /* -* Verify the IV is not set +* ECB_Encryption Constructor */ -bool ECB::valid_iv_size(u32bit iv_size) const +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) { - if(iv_size == 0) - return true; - return false; + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Encryption Constructor +*/ +ECB_Encryption::ECB_Encryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + plaintext.create(cipher->BLOCK_SIZE); + ciphertext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + cipher->set_key(key); + } + +/* +* ECB_Encryption Destructor +*/ +ECB_Encryption::~ECB_Encryption() + { + delete cipher; + delete padder; } /* * Return an ECB mode name */ -std::string ECB::name() const +std::string ECB_Encryption::name() const { - return (cipher->name() + "/" + mode_name + "/" + padder->name()); + return (cipher->name() + "/ECB/" + padder->name()); } /* @@ -32,23 +70,34 @@ std::string ECB::name() const */ void ECB_Encryption::write(const byte input[], u32bit length) { - buffer.copy(position, input, length); - if(position + length >= BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->encrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length >= BLOCK_SIZE) + plaintext.copy(position, input, length); + + if(position + length >= BLOCK_SIZE) { - cipher->encrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->encrypt(plaintext, ciphertext); + send(ciphertext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - position = 0; } + + while(length >= BLOCK_SIZE) + { + const u32bit to_proc = + std::min<u32bit>(length, ciphertext.size()) / BLOCK_SIZE; + + cipher->encrypt_n(input, ciphertext, to_proc); + send(ciphertext, to_proc * BLOCK_SIZE); + input += to_proc * BLOCK_SIZE; + length -= to_proc * BLOCK_SIZE; + } + + plaintext.copy(position, input, length); position += length; } @@ -57,6 +106,8 @@ void ECB_Encryption::write(const byte input[], u32bit length) */ void ECB_Encryption::end_msg() { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + SecureVector<byte> padding(BLOCK_SIZE); padder->pad(padding, padding.size(), position); write(padding, padder->pad_bytes(BLOCK_SIZE, position)); @@ -65,27 +116,93 @@ void ECB_Encryption::end_msg() } /* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + } + +/* +* ECB_Decryption Constructor +*/ +ECB_Decryption::ECB_Decryption(BlockCipher* ciph, + BlockCipherModePaddingMethod* pad, + const SymmetricKey& key) + { + cipher = ciph; + padder = pad; + + ciphertext.create(cipher->BLOCK_SIZE); + plaintext.create(cipher->BLOCK_SIZE * PARALLEL_BLOCKS); + + position = 0; + + cipher->set_key(key); + } + +/* +* ECB_Decryption Destructor +*/ +ECB_Decryption::~ECB_Decryption() + { + delete cipher; + delete padder; + } + +/* +* Return an ECB mode name +*/ +std::string ECB_Decryption::name() const + { + return (cipher->name() + "/ECB/" + padder->name()); + } + +/* * Decrypt in ECB mode */ void ECB_Decryption::write(const byte input[], u32bit length) { - buffer.copy(position, input, length); - if(position + length > BLOCK_SIZE) + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + if(position) { - cipher->decrypt(buffer); - send(buffer, BLOCK_SIZE); - input += (BLOCK_SIZE - position); - length -= (BLOCK_SIZE - position); - while(length > BLOCK_SIZE) + ciphertext.copy(position, input, length); + + if(position + length > BLOCK_SIZE) { - cipher->decrypt(input, buffer); - send(buffer, BLOCK_SIZE); - input += BLOCK_SIZE; - length -= BLOCK_SIZE; + cipher->decrypt(ciphertext, plaintext); + send(plaintext, BLOCK_SIZE); + input += (BLOCK_SIZE - position); + length -= (BLOCK_SIZE - position); + position = 0; } - buffer.copy(input, length); - position = 0; } + + while(length > BLOCK_SIZE) + { + /* Always leave at least 1 byte left over, to ensure that (as long + as the input message actually is a multiple of the block size) + we will have the full final block left over in end_msg so as + to remove the padding + */ + const u32bit to_proc = + std::min<u32bit>(length - 1, plaintext.size()) / BLOCK_SIZE; + + cipher->decrypt_n(input, plaintext, to_proc); + send(plaintext, to_proc * BLOCK_SIZE); + input += to_proc * BLOCK_SIZE; + length -= to_proc * BLOCK_SIZE; + } + + ciphertext.copy(position, input, length); position += length; } @@ -94,11 +211,11 @@ void ECB_Decryption::write(const byte input[], u32bit length) */ void ECB_Decryption::end_msg() { - if(position != BLOCK_SIZE) + if(position != cipher->BLOCK_SIZE) throw Decoding_Error(name()); - cipher->decrypt(buffer); - send(buffer, padder->unpad(buffer, BLOCK_SIZE)); - state = buffer; + + cipher->decrypt(ciphertext); + send(ciphertext, padder->unpad(ciphertext, cipher->BLOCK_SIZE)); position = 0; } diff --git a/src/modes/ecb/ecb.h b/src/modes/ecb/ecb.h index 5230f9b14..ff9ea9635 100644 --- a/src/modes/ecb/ecb.h +++ b/src/modes/ecb/ecb.h @@ -1,6 +1,6 @@ /* * ECB Mode -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2009 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,64 +8,74 @@ #ifndef BOTAN_ECB_H__ #define BOTAN_ECB_H__ -#include <botan/modebase.h> -#include <botan/mode_pad.h> +#include <botan/basefilt.h> #include <botan/block_cipher.h> +#include <botan/mode_pad.h> -namespace Botan { - -/* -* ECB -*/ -class BOTAN_DLL ECB : public BlockCipherMode - { - protected: - ECB(BlockCipher* ciph, BlockCipherModePaddingMethod* pad) : - BlockCipherMode(ciph, "ECB", 0), padder(pad) {} - ~ECB() { delete padder; } +#include <botan/modebase.h> - std::string name() const; - BlockCipherModePaddingMethod* padder; - private: - bool valid_iv_size(u32bit) const; - }; +namespace Botan { /* * ECB Encryption */ -class BOTAN_DLL ECB_Encryption : public ECB +class BOTAN_DLL ECB_Encryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Encryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Encryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Encryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; /* * ECB Decryption */ -class BOTAN_DLL ECB_Decryption : public ECB +class BOTAN_DLL ECB_Decryption : public Keyed_Filter { public: + std::string name() const; + + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + ECB_Decryption(BlockCipher* ciph, - BlockCipherModePaddingMethod* pad) : - ECB(ciph, pad) {} + BlockCipherModePaddingMethod* pad); ECB_Decryption(BlockCipher* ciph, BlockCipherModePaddingMethod* pad, - const SymmetricKey& key) : - ECB(ciph, pad) { set_key(key); } + const SymmetricKey& key); + + ~ECB_Decryption(); private: void write(const byte[], u32bit); void end_msg(); + + BlockCipher* cipher; + BlockCipherModePaddingMethod* padder; + SecureVector<byte> plaintext, ciphertext; + u32bit position; }; } diff --git a/src/modes/modebase.cpp b/src/modes/modebase.cpp index 8293acc54..b048862a4 100644 --- a/src/modes/modebase.cpp +++ b/src/modes/modebase.cpp @@ -19,7 +19,7 @@ BlockCipherMode::BlockCipherMode(BlockCipher* cipher_ptr, BLOCK_SIZE(cipher_ptr->BLOCK_SIZE), BUFFER_SIZE(buf_mult * BLOCK_SIZE), IV_METHOD(iv_meth), mode_name(cipher_mode_name) { - base_ptr = cipher = cipher_ptr; + cipher = cipher_ptr; buffer.create(BUFFER_SIZE); state.create(iv_size); position = 0; diff --git a/src/modes/modebase.h b/src/modes/modebase.h index 173fde58c..4a15524b6 100644 --- a/src/modes/modebase.h +++ b/src/modes/modebase.h @@ -8,7 +8,7 @@ #ifndef BOTAN_MODEBASE_H__ #define BOTAN_MODEBASE_H__ -#include <botan/basefilt.h> +#include <botan/key_filt.h> #include <botan/block_cipher.h> namespace Botan { @@ -21,12 +21,17 @@ class BOTAN_DLL BlockCipherMode : public Keyed_Filter public: std::string name() const; + void set_iv(const InitializationVector&); + void set_key(const SymmetricKey& key) { cipher->set_key(key); } + + bool valid_keylength(u32bit key_len) const + { return cipher->valid_keylength(key_len); } + BlockCipherMode(BlockCipher*, const std::string&, u32bit, u32bit = 0, u32bit = 1); virtual ~BlockCipherMode() { delete cipher; } protected: - void set_iv(const InitializationVector&); const u32bit BLOCK_SIZE, BUFFER_SIZE, IV_METHOD; const std::string mode_name; BlockCipher* cipher; diff --git a/src/modes/xts/xts.cpp b/src/modes/xts/xts.cpp index 8819c85dc..8780ae166 100644 --- a/src/modes/xts/xts.cpp +++ b/src/modes/xts/xts.cpp @@ -41,7 +41,6 @@ XTS_Encryption::XTS_Encryption(BlockCipher* ciph) : cipher(ciph) throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); - buffer.create(cipher->BLOCK_SIZE); tweak.create(cipher->BLOCK_SIZE); buffer.create(2 * cipher->BLOCK_SIZE); position = 0; @@ -58,7 +57,6 @@ XTS_Encryption::XTS_Encryption(BlockCipher* ciph, throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); cipher2 = cipher->clone(); - buffer.create(cipher->BLOCK_SIZE); tweak.create(cipher->BLOCK_SIZE); buffer.create(2 * cipher->BLOCK_SIZE); position = 0; @@ -188,6 +186,8 @@ void XTS_Encryption::end_msg() send(buffer, position); } + + position = 0; } /* @@ -197,7 +197,6 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph) { cipher = ciph; cipher2 = ciph->clone(); - buffer.create(cipher->BLOCK_SIZE); tweak.create(cipher->BLOCK_SIZE); buffer.create(2 * cipher->BLOCK_SIZE); position = 0; @@ -212,7 +211,6 @@ XTS_Decryption::XTS_Decryption(BlockCipher* ciph, { cipher = ciph; cipher2 = ciph->clone(); - buffer.create(cipher->BLOCK_SIZE); tweak.create(cipher->BLOCK_SIZE); buffer.create(2 * cipher->BLOCK_SIZE); position = 0; @@ -339,6 +337,8 @@ void XTS_Decryption::end_msg() send(buffer, position); } + + position = 0; } } 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/pubkey/dsa/dsa_core.cpp b/src/pubkey/dsa/dsa_core.cpp index e144d2467..e5a23a5c3 100644 --- a/src/pubkey/dsa/dsa_core.cpp +++ b/src/pubkey/dsa/dsa_core.cpp @@ -13,12 +13,6 @@ namespace Botan { -namespace { - -const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - -} - /* * DSA_Core Constructor */ diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index bebfc3705..6c7d02c74 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -57,7 +57,7 @@ void EC_PublicKey::X509_load_hook() affirm_init(); mp_public_point->check_invariants(); } - catch(Illegal_Point exc) + catch(Illegal_Point) { throw Decoding_Error("decoded public point was found not to lie on curve"); } diff --git a/src/pubkey/eckaeg/eckaeg.cpp b/src/pubkey/eckaeg/eckaeg.cpp index 1b315d101..5787f062d 100644 --- a/src/pubkey/eckaeg/eckaeg.cpp +++ b/src/pubkey/eckaeg/eckaeg.cpp @@ -129,9 +129,10 @@ MemoryVector<byte> ECKAEG_PrivateKey::public_value() const /** * Derive a key */ -SecureVector<byte> ECKAEG_PrivateKey::derive_key(const byte key[], u32bit key_len) const +SecureVector<byte> ECKAEG_PrivateKey::derive_key(const byte key[], + u32bit key_len) const { - MemoryVector<byte> key_x(key, key_len); // XXX fix this, nasty/slow + MemoryVector<byte> key_x(key, key_len); // FIXME: nasty/slow PointGFp point = OS2ECP(key_x, public_point().get_curve()); return m_eckaeg_core.agree(point); diff --git a/src/pubkey/pk_codecs/pkcs8.h b/src/pubkey/pk_codecs/pkcs8.h index 87f8ba326..28008bdba 100644 --- a/src/pubkey/pk_codecs/pkcs8.h +++ b/src/pubkey/pk_codecs/pkcs8.h @@ -30,7 +30,7 @@ class BOTAN_DLL PKCS8_Encoder * Get the DER encoded key. * @return the DER encoded key */ - // XXX: Why not SecureVector? + // FIXME: Why not SecureVector? virtual MemoryVector<byte> key_bits() const = 0; virtual ~PKCS8_Encoder() {} }; @@ -117,11 +117,6 @@ BOTAN_DLL std::string PEM_encode(const Private_Key& key, const std::string& pass, const std::string& pbe_algo = ""); -BOTAN_DLL std::string PEM_encode(const Private_Key&, - const std::string&, - const std::string& = ""); - - /** * Load a key from a data source. * @param source the data source providing the encoded key diff --git a/src/rng/auto_rng/auto_rng.cpp b/src/rng/auto_rng/auto_rng.cpp index 171c83cca..07b2ddec2 100644 --- a/src/rng/auto_rng/auto_rng.cpp +++ b/src/rng/auto_rng/auto_rng.cpp @@ -140,7 +140,7 @@ AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits) #endif if(!rng) - throw Algorithm_Not_Found("No usable RNG found enabled in build"); + throw Internal_Error("No usable RNG found enabled in build"); /* If X9.31 is available, use it to wrap the other RNG as a failsafe */ #if defined(BOTAN_HAS_X931_RNG) diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index ea032b04e..d644e866e 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -173,7 +173,7 @@ bool passes_self_tests(Algorithm_Factory& af) "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); } } - catch(std::exception& e) + catch(std::exception) { return false; } diff --git a/src/stream/turing/turing.cpp b/src/stream/turing/turing.cpp index b988568c3..1e2203480 100644 --- a/src/stream/turing/turing.cpp +++ b/src/stream/turing/turing.cpp @@ -218,25 +218,6 @@ u32bit Turing::fixedS(u32bit W) } /* -* Generate the expanded Turing Sbox tables -*/ -void Turing::gen_sbox(MemoryRegion<u32bit>& S, u32bit which, - const MemoryRegion<u32bit>& K) - { - for(u32bit j = 0; j != 256; ++j) - { - u32bit W = 0, C = j; - - for(u32bit k = 0; k < K.size(); ++k) - { - C = SBOX[get_byte(which, K[k]) ^ C]; - W ^= rotate_left(Q_BOX[C], k + 8*which); - } - S[j] = (W & rotate_right(0x00FFFFFF, 8*which)) | (C << (24 - 8*which)); - } - } - -/* * Turing Key Schedule */ void Turing::key_schedule(const byte key[], u32bit length) @@ -250,10 +231,31 @@ void Turing::key_schedule(const byte key[], u32bit length) PHT(K); - gen_sbox(S0, 0, K); - gen_sbox(S1, 1, K); - gen_sbox(S2, 2, K); - gen_sbox(S3, 3, K); + for(u32bit i = 0; i != 256; ++i) + { + u32bit W0 = 0, C0 = i; + u32bit W1 = 0, C1 = i; + u32bit W2 = 0, C2 = i; + u32bit W3 = 0, C3 = i; + + for(u32bit j = 0; j < K.size(); ++j) + { + C0 = SBOX[get_byte(0, K[j]) ^ C0]; + C1 = SBOX[get_byte(1, K[j]) ^ C1]; + C2 = SBOX[get_byte(2, K[j]) ^ C2]; + C3 = SBOX[get_byte(3, K[j]) ^ C3]; + + W0 ^= rotate_left(Q_BOX[C0], j); + W1 ^= rotate_left(Q_BOX[C1], j + 8); + W2 ^= rotate_left(Q_BOX[C2], j + 16); + W3 ^= rotate_left(Q_BOX[C3], j + 24); + } + + S0[i] = (W0 & 0x00FFFFFF) | (C0 << 24); + S1[i] = (W1 & 0xFF00FFFF) | (C1 << 16); + S2[i] = (W2 & 0xFFFF00FF) | (C2 << 8); + S3[i] = (W3 & 0xFFFFFF00) | C3; + } resync(0, 0); } diff --git a/src/stream/turing/turing.h b/src/stream/turing/turing.h index d48c1d8a8..455d3c612 100644 --- a/src/stream/turing/turing.h +++ b/src/stream/turing/turing.h @@ -29,8 +29,6 @@ class BOTAN_DLL Turing : public StreamCipher void generate(); static u32bit fixedS(u32bit); - static void gen_sbox(MemoryRegion<u32bit>&, u32bit, - const MemoryRegion<u32bit>&); static const u32bit Q_BOX[256]; static const byte SBOX[256]; diff --git a/src/timer/gettimeofday/info.txt b/src/timer/gettimeofday/info.txt index d3812eedf..a58e8088d 100644 --- a/src/timer/gettimeofday/info.txt +++ b/src/timer/gettimeofday/info.txt @@ -16,6 +16,7 @@ beos cygwin darwin freebsd +dragonfly hpux irix linux diff --git a/src/timer/posix_rt/info.txt b/src/timer/posix_rt/info.txt index 7501373bb..fa530ea1a 100644 --- a/src/timer/posix_rt/info.txt +++ b/src/timer/posix_rt/info.txt @@ -18,6 +18,7 @@ linux -> rt cygwin linux #freebsd +dragonfly #netbsd #openbsd </os> diff --git a/src/utils/bswap.h b/src/utils/bswap.h index af51e4e47..08095b319 100644 --- a/src/utils/bswap.h +++ b/src/utils/bswap.h @@ -31,9 +31,9 @@ inline u32bit reverse_bytes(u32bit input) asm("bswapl %0" : "=r" (input) : "0" (input)); return input; -#elif defined(_MSC_VER) && defined(BOTAN_TARGER_ARCH_IS_IA32) +#elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32) /* Visual C++ inline asm for 32-bit x86, by Yves Jerschow */ - __asm mov eax, x; + __asm mov eax, input; __asm bswap eax; #else diff --git a/src/utils/info.txt b/src/utils/info.txt index 95ea5fc2e..ab50b88ad 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -2,7 +2,7 @@ realname "Utility Functions" define UTIL_FUNCTIONS -load_on auto +load_on always <libs> tru64 -> rt |