diff options
author | Jack Lloyd <[email protected]> | 2016-09-17 14:20:03 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-09-17 14:20:03 -0400 |
commit | d734198074d0290631e27d1fb27dce45f0676d58 (patch) | |
tree | faed46aaae836e44e972a4e6d5bdea06b0729034 /src/tests | |
parent | 272fcf00572432f64085b10132e364740d7eb093 (diff) | |
parent | 2b7f2d52d032ad56526d38e7f65bd966ac59325a (diff) |
Merge GH #623 Merge algorithm impl types
If CPU specific optimizations are available they are always used,
without requiring the application to use the application registry to
ensure they get the optimal type.
See also GH #477
Diffstat (limited to 'src/tests')
-rw-r--r-- | src/tests/data/aead/gcm.vec | 3 | ||||
-rw-r--r-- | src/tests/data/block/aes.vec | 3 | ||||
-rw-r--r-- | src/tests/data/block/idea.vec | 3 | ||||
-rw-r--r-- | src/tests/data/block/noekeon.vec | 3 | ||||
-rw-r--r-- | src/tests/data/block/serpent.vec | 3 | ||||
-rw-r--r-- | src/tests/data/block/threefish.vec | 3 | ||||
-rw-r--r-- | src/tests/data/hash/sha1.vec | 2 | ||||
-rw-r--r-- | src/tests/data/stream/chacha.vec | 3 | ||||
-rw-r--r-- | src/tests/main.cpp | 20 | ||||
-rw-r--r-- | src/tests/test_block.cpp | 8 | ||||
-rw-r--r-- | src/tests/test_hash.cpp | 8 | ||||
-rw-r--r-- | src/tests/test_mac.cpp | 9 | ||||
-rw-r--r-- | src/tests/test_modes.cpp | 1 | ||||
-rw-r--r-- | src/tests/test_stream.cpp | 8 | ||||
-rw-r--r-- | src/tests/tests.cpp | 117 | ||||
-rw-r--r-- | src/tests/tests.h | 5 |
16 files changed, 169 insertions, 30 deletions
diff --git a/src/tests/data/aead/gcm.vec b/src/tests/data/aead/gcm.vec index 516e828ec..be8250792 100644 --- a/src/tests/data/aead/gcm.vec +++ b/src/tests/data/aead/gcm.vec @@ -1,3 +1,6 @@ + +#test cpuid aesni ssse3 clmul + [AES-128/GCM] # Nist | Test Case 1 Key = 00000000000000000000000000000000 diff --git a/src/tests/data/block/aes.vec b/src/tests/data/block/aes.vec index 4e0b7399c..50d9cc469 100644 --- a/src/tests/data/block/aes.vec +++ b/src/tests/data/block/aes.vec @@ -1,3 +1,6 @@ + +#test cpuid aesni ssse3 + [AES-128] Key = 000102030405060708090A0B0C0D0E0F In = 00112233445566778899AABBCCDDEEFF diff --git a/src/tests/data/block/idea.vec b/src/tests/data/block/idea.vec index 705d02d68..eee5ef5e9 100644 --- a/src/tests/data/block/idea.vec +++ b/src/tests/data/block/idea.vec @@ -1,3 +1,6 @@ + +#test cpuid sse2 + [IDEA] Key = ED1BCC9E9267925F3132BA3A8CF9B764 In = 7409000000000000 diff --git a/src/tests/data/block/noekeon.vec b/src/tests/data/block/noekeon.vec index 2921301c1..08e7cabf3 100644 --- a/src/tests/data/block/noekeon.vec +++ b/src/tests/data/block/noekeon.vec @@ -1,3 +1,6 @@ + +#cpuid simd32 + [Noekeon] Key = 00000000000000000000000000000000 In = 00000000000000000000000000000000 diff --git a/src/tests/data/block/serpent.vec b/src/tests/data/block/serpent.vec index 623ee6be8..8a40c54b7 100644 --- a/src/tests/data/block/serpent.vec +++ b/src/tests/data/block/serpent.vec @@ -1,3 +1,6 @@ + +#test cpuid simd + [Serpent] Key = 00000000000000000000000000000000 In = D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78ED29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78ED29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78ED29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78ED29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871D29D576F315C5C58126F660D6D8C2871 diff --git a/src/tests/data/block/threefish.vec b/src/tests/data/block/threefish.vec index b4e9d8229..dfaccb7ff 100644 --- a/src/tests/data/block/threefish.vec +++ b/src/tests/data/block/threefish.vec @@ -1,3 +1,6 @@ + +#test cpuid avx2 + [Threefish-512] Key = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/src/tests/data/hash/sha1.vec b/src/tests/data/hash/sha1.vec index f5fd82340..e86650f30 100644 --- a/src/tests/data/hash/sha1.vec +++ b/src/tests/data/hash/sha1.vec @@ -1,3 +1,5 @@ +#test cpuid sse2 + [SHA-160] In = Out = DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 diff --git a/src/tests/data/stream/chacha.vec b/src/tests/data/stream/chacha.vec index 47d3aa7fe..f7ba701ba 100644 --- a/src/tests/data/stream/chacha.vec +++ b/src/tests/data/stream/chacha.vec @@ -1,3 +1,6 @@ + +#test cpuid sse2 + [ChaCha(8)] # Tests got from the original implementation of Daniel J. Bernstein diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 07aaac519..b771d9614 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -228,8 +228,14 @@ class Test_Runner : public Botan_CLI::Command { for(auto&& test_name : tests_to_run) { - const auto results = Botan_Tests::Test::run_test(test_name, false); - out << report_out(results, tests_failed, tests_ran) << std::flush; + try { + const auto results = Botan_Tests::Test::run_test(test_name, false); + out << report_out(results, tests_failed, tests_ran) << std::flush; + } + catch(std::exception& e) + { + out << "Test " << test_name << " failed with exception " << e.what() << std::flush; + } } } else @@ -250,7 +256,15 @@ class Test_Runner : public Botan_CLI::Command for(auto&& test_name : tests_to_run) { auto run_it = [test_name] { - return Botan_Tests::Test::run_test(test_name, false); + try { + return Botan_Tests::Test::run_test(test_name, false); + } + catch(std::exception& e) + { + Botan_Tests::Test::Result r(test_name); + r.test_failure("Exception thrown", e.what()); + return std::vector<Botan_Tests::Test::Result>{r}; + } }; fut_results.push_back(std::async(std::launch::async, run_it)); diff --git a/src/tests/test_block.cpp b/src/tests/test_block.cpp index 0863cb891..acbe6702b 100644 --- a/src/tests/test_block.cpp +++ b/src/tests/test_block.cpp @@ -30,16 +30,18 @@ class Block_Cipher_Tests : public Text_Based_Test return result; } - for(auto&& provider: providers) + for(auto&& provider_ask : providers) { - std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(algo, provider)); + std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(algo, provider_ask)); if(!cipher) { - result.note_missing(algo + " from " + provider); + result.note_missing(algo + " from " + provider_ask); continue; } + const std::string provider(cipher->provider()); + result.test_is_nonempty("provider", provider); result.test_eq(provider, cipher->name(), algo); result.test_gte(provider, cipher->parallelism(), 1); result.test_gte(provider, cipher->block_size(), 8); diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp index 811e95727..aca9d7ef6 100644 --- a/src/tests/test_hash.cpp +++ b/src/tests/test_hash.cpp @@ -36,16 +36,18 @@ class Hash_Function_Tests : public Text_Based_Test return result; } - for(auto&& provider: providers) + for(auto&& provider_ask : providers) { - std::unique_ptr<Botan::HashFunction> hash(Botan::HashFunction::create(algo, provider)); + std::unique_ptr<Botan::HashFunction> hash(Botan::HashFunction::create(algo, provider_ask)); if(!hash) { - result.note_missing(algo + " from " + provider); + result.note_missing(algo + " from " + provider_ask); continue; } + const std::string provider(hash->provider()); + result.test_is_nonempty("provider", provider); result.test_eq(provider, hash->name(), algo); hash->update(input); diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp index c7efb7f08..6183e88f7 100644 --- a/src/tests/test_mac.cpp +++ b/src/tests/test_mac.cpp @@ -38,16 +38,19 @@ class Message_Auth_Tests : public Text_Based_Test return result; } - for(auto&& provider: providers) + for(auto&& provider_ask : providers) { - std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create(algo, provider)); + std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create(algo, provider_ask)); if(!mac) { - result.note_missing(algo + " from " + provider); + result.note_missing(algo + " from " + provider_ask); continue; } + const std::string provider(mac->provider()); + + result.test_is_nonempty("provider", provider); result.test_eq(provider, mac->name(), algo); mac->set_key(key); diff --git a/src/tests/test_modes.cpp b/src/tests/test_modes.cpp index 66f537346..ada4d5b82 100644 --- a/src/tests/test_modes.cpp +++ b/src/tests/test_modes.cpp @@ -39,6 +39,7 @@ class Cipher_Mode_Tests : public Text_Based_Test return result; } + result.test_is_nonempty("provider", enc->provider()); result.test_eq("name", enc->name(), algo); result.test_eq("mode not authenticated", enc->authenticated(), false); diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp index be7b9a548..6097fd3e8 100644 --- a/src/tests/test_stream.cpp +++ b/src/tests/test_stream.cpp @@ -41,16 +41,18 @@ class Stream_Cipher_Tests : public Text_Based_Test return result; } - for(auto&& provider: providers) + for(auto&& provider_ask : providers) { - std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider)); + std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider_ask)); if(!cipher) { - result.note_missing(algo + " from " + provider); + result.note_missing(algo + " from " + provider_ask); continue; } + const std::string provider(cipher->provider()); + result.test_is_nonempty("provider", provider); result.test_eq(provider, cipher->name(), algo); cipher->set_key(key); diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index a6f96144c..b47f2a7ab 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -175,6 +175,13 @@ bool Test::Result::test_eq(const char* producer, const std::string& what, return test_failure(err.str()); } +bool Test::Result::test_is_nonempty(const std::string& what_is_it, const std::string& to_examine) + { + if(to_examine.empty()) + return test_failure(what_is_it + " was empty"); + return test_success(); + } + bool Test::Result::test_eq(const std::string& what, const std::string& produced, const std::string& expected) { return test_is_eq(what, produced, expected); @@ -527,21 +534,21 @@ Text_Based_Test::Text_Based_Test(const std::string& algo, std::vector<uint8_t> Text_Based_Test::get_req_bin(const VarMap& vars, const std::string& key) const - { - auto i = vars.find(key); - if(i == vars.end()) - throw Test_Error("Test missing variable " + key); + { + auto i = vars.find(key); + if(i == vars.end()) + throw Test_Error("Test missing variable " + key); - try - { - return Botan::hex_decode(i->second); - } - catch(std::exception&) - { - throw Test_Error("Test invalid hex input '" + i->second + "'" + - + " for key " + key); - } + try + { + return Botan::hex_decode(i->second); } + catch(std::exception&) + { + throw Test_Error("Test invalid hex input '" + i->second + "'" + + + " for key " + key); + } + } std::string Text_Based_Test::get_opt_str(const VarMap& vars, const std::string& key, const std::string& def_value) const @@ -646,9 +653,17 @@ std::string Text_Based_Test::get_next_line() } m_cur.reset(new std::ifstream(m_srcs[0])); + m_cur_src_name = m_srcs[0]; + + // Reinit cpuid on new file if needed + if(m_cpu_flags.empty() == false) + { + m_cpu_flags.clear(); + Botan::CPUID::initialize(); + } if(!m_cur->good()) - throw Test_Error("Could not open input file '" + m_srcs[0]); + throw Test_Error("Could not open input file '" + m_cur_src_name); m_srcs.pop_front(); } @@ -662,7 +677,12 @@ std::string Text_Based_Test::get_next_line() continue; if(line[0] == '#') - continue; + { + if(line.compare(0, 6, "#test ") == 0) + return line; + else + continue; + } return line; } @@ -685,6 +705,42 @@ std::string strip_ws(const std::string& in) return in.substr(first_c, last_c - first_c + 1); } +std::vector<Botan::CPUID::CPUID_bits> map_cpuid_string(const std::string& tok) + { +#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) + if(tok == "sse2" || tok == "simd") + return {Botan::CPUID::CPUID_SSE2_BIT}; + if(tok == "ssse3") + return {Botan::CPUID::CPUID_SSSE3_BIT}; + if(tok == "aesni") + return {Botan::CPUID::CPUID_AESNI_BIT}; + if(tok == "clmul") + return {Botan::CPUID::CPUID_CLMUL_BIT}; + if(tok == "avx2") + return {Botan::CPUID::CPUID_AVX2_BIT}; +#endif + +#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) + if(tok == "altivec" || tok == "simd") + return {Botan::CPUID::CPUID_ALTIVEC_BIT}; +#endif + + return {}; + } + +std::vector<Botan::CPUID::CPUID_bits> +parse_cpuid_bits(const std::vector<std::string>& tok) + { + std::vector<Botan::CPUID::CPUID_bits> bits; + for(size_t i = 1; i < tok.size(); ++i) + { + const std::vector<Botan::CPUID::CPUID_bits> more = map_cpuid_string(tok[i]); + bits.insert(bits.end(), more.begin(), more.end()); + } + + return bits; + } + } std::vector<Test::Result> Text_Based_Test::run() @@ -701,6 +757,23 @@ std::vector<Test::Result> Text_Based_Test::run() if(line.empty()) // EOF break; + if(line.compare(0, 6, "#test ") == 0) + { + std::vector<std::string> pragma_tokens = Botan::split_on(line.substr(6), ' '); + + if(pragma_tokens.empty()) + throw Test_Error("Empty pragma found in " + m_cur_src_name); + + if(pragma_tokens[0] != "cpuid") + throw Test_Error("Unknown test pragma '" + line + "' in " + m_cur_src_name); + + m_cpu_flags = parse_cpuid_bits(pragma_tokens); + + continue; + } + else if(line[0] == '#') + throw Test_Error("Unknown test pragma '" + line + "' in " + m_cur_src_name); + if(line[0] == '[' && line[line.size()-1] == ']') { header = line.substr(1, line.size() - 2); @@ -736,7 +809,21 @@ std::vector<Test::Result> Text_Based_Test::run() ++test_cnt; uint64_t start = Test::timestamp(); + Test::Result result = run_one_test(header, vars); + if(m_cpu_flags.size() > 0) + { + for(auto&& cpuid_bit : m_cpu_flags) + { + if(Botan::CPUID::has_cpuid_bit(cpuid_bit)) + { + Botan::CPUID::clear_cpuid_bit(cpuid_bit); + // now re-run the test + result.merge(run_one_test(header, vars)); + } + } + Botan::CPUID::initialize(); + } result.set_ns_consumed(Test::timestamp() - start); if(result.tests_failed()) diff --git a/src/tests/tests.h b/src/tests/tests.h index 39aaf67cd..1ceb24f48 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -12,6 +12,7 @@ #include <botan/rng.h> #include <botan/hex.h> #include <botan/symkey.h> +#include <botan/cpuid.h> #if defined(BOTAN_HAS_BIGINT) #include <botan/bigint.h> @@ -170,6 +171,8 @@ class Test bool test_eq(const std::string& what, const char* produced, const char* expected); + bool test_is_nonempty(const std::string& what_is_it, const std::string& to_examine); + bool test_eq(const std::string& what, const std::string& produced, const std::string& expected); @@ -442,7 +445,9 @@ class Text_Based_Test : public Test bool m_first = true; std::unique_ptr<std::ifstream> m_cur; + std::string m_cur_src_name; std::deque<std::string> m_srcs; + std::vector<Botan::CPUID::CPUID_bits> m_cpu_flags; }; } |