From dc5aa5be4d254f9f7e9b68cd265058011462cdaf Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 14 Sep 2016 12:39:05 -0400 Subject: Add cpuid overload to test framework --- src/tests/data/aead/gcm.vec | 3 + src/tests/data/block/aes.vec | 3 + src/tests/data/block/idea.vec | 3 + src/tests/data/block/noekeon.vec | 3 + src/tests/data/block/serpent.vec | 3 + src/tests/data/block/threefish.vec | 3 + src/tests/data/hash/sha1.vec | 2 + src/tests/data/stream/chacha.vec | 3 + src/tests/tests.cpp | 113 ++++++++++++++++++++++++++++++++----- src/tests/tests.h | 3 + 10 files changed, 124 insertions(+), 15 deletions(-) (limited to 'src/tests') 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/tests.cpp b/src/tests/tests.cpp index a6f96144c..2913e5445 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -527,21 +527,21 @@ Text_Based_Test::Text_Based_Test(const std::string& algo, std::vector 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 +646,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 +670,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 +698,42 @@ std::string strip_ws(const std::string& in) return in.substr(first_c, last_c - first_c + 1); } +std::vector 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_ALITVEC_BIT}; +#endif + + return {}; + } + +std::vector +parse_cpuid_bits(const std::vector& tok) + { + std::vector bits; + for(size_t i = 1; i < tok.size(); ++i) + { + const std::vector more = map_cpuid_string(tok[i]); + bits.insert(bits.end(), more.begin(), more.end()); + } + + return bits; + } + } std::vector Text_Based_Test::run() @@ -701,6 +750,26 @@ std::vector Text_Based_Test::run() if(line.empty()) // EOF break; + if(line.compare(0, 6, "#test ") == 0) + { + std::vector 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); + + if(m_cpu_flags.empty()) + throw Test_Error("Empty cpuid pragma in " + m_cur_src_name); + + 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 +805,21 @@ std::vector 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..43b9e0d3a 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -12,6 +12,7 @@ #include #include #include +#include #if defined(BOTAN_HAS_BIGINT) #include @@ -442,7 +443,9 @@ class Text_Based_Test : public Test bool m_first = true; std::unique_ptr m_cur; + std::string m_cur_src_name; std::deque m_srcs; + std::vector m_cpu_flags; }; } -- cgit v1.2.3 From a7eba3629cc0d76444f5241fb4b9e8793ddb61cd Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 14 Sep 2016 13:09:11 -0400 Subject: Fix build on PowerPC. Fix test runs on non-x86 --- src/tests/tests.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/tests') diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index 2913e5445..2e8a1e4de 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -715,7 +715,7 @@ std::vector map_cpuid_string(const std::string& tok) #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) if(tok == "altivec" || tok == "simd") - return {Botan::CPUID::CPUID_ALITVEC_BIT}; + return {Botan::CPUID::CPUID_ALTIVEC_BIT}; #endif return {}; @@ -762,9 +762,6 @@ std::vector Text_Based_Test::run() m_cpu_flags = parse_cpuid_bits(pragma_tokens); - if(m_cpu_flags.empty()) - throw Test_Error("Empty cpuid pragma in " + m_cur_src_name); - continue; } else if(line[0] == '#') -- cgit v1.2.3 From 04bf8dc51861bab37d6260de8b318dc71ea4bba7 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 15 Sep 2016 09:16:46 -0400 Subject: Add T::provider() to allow user to inquire about implementation used For block ciphers, stream ciphers, hashes, MACs, and cipher modes. Cipher_Mode already had it, with a slightly different usage. --- src/lib/block/aes/aes.cpp | 23 +++++++++++++++++++++++ src/lib/block/aes/aes.h | 4 ++++ src/lib/block/block_cipher.h | 8 ++++++++ src/lib/block/idea/idea.cpp | 12 ++++++++++++ src/lib/block/idea/idea.h | 2 ++ src/lib/block/noekeon/noekeon.cpp | 12 ++++++++++++ src/lib/block/noekeon/noekeon.h | 1 + src/lib/block/serpent/serpent.cpp | 12 ++++++++++++ src/lib/block/serpent/serpent.h | 1 + src/lib/block/threefish/threefish.cpp | 12 ++++++++++++ src/lib/block/threefish/threefish.h | 1 + src/lib/hash/hash.h | 7 +++++++ src/lib/mac/mac.h | 8 ++++++++ src/lib/modes/aead/gcm/gcm.cpp | 10 ++++++++++ src/lib/modes/aead/gcm/gcm.h | 2 ++ src/lib/modes/cipher_mode.h | 15 +++++++-------- src/lib/prov/openssl/openssl_block.cpp | 1 + src/lib/prov/openssl/openssl_hash.cpp | 1 + src/lib/prov/openssl/openssl_rc4.cpp | 2 ++ src/lib/stream/chacha/chacha.cpp | 12 ++++++++++++ src/lib/stream/chacha/chacha.h | 2 ++ src/lib/stream/stream_cipher.h | 7 +++++++ src/tests/test_block.cpp | 8 +++++--- src/tests/test_hash.cpp | 8 +++++--- src/tests/test_mac.cpp | 9 ++++++--- src/tests/test_modes.cpp | 1 + src/tests/test_stream.cpp | 8 +++++--- src/tests/tests.cpp | 7 +++++++ src/tests/tests.h | 2 ++ 29 files changed, 178 insertions(+), 20 deletions(-) (limited to 'src/tests') diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp index eb24ce5a3..9483dc0eb 100644 --- a/src/lib/block/aes/aes.cpp +++ b/src/lib/block/aes/aes.cpp @@ -416,8 +416,31 @@ void aes_key_schedule(const byte key[], size_t length, copy_mem(DK.data(), XDK.data(), DK.size()); } +const char* aes_provider() + { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return "aesni"; + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return "ssse3"; + } +#endif + + return "base"; + } + } +const char* AES_128::provider() const { return aes_provider(); } +const char* AES_192::provider() const { return aes_provider(); } +const char* AES_256::provider() const { return aes_provider(); } + void AES_128::encrypt_n(const byte in[], byte out[], size_t blocks) const { #if defined(BOTAN_HAS_AES_NI) diff --git a/src/lib/block/aes/aes.h b/src/lib/block/aes/aes.h index d6b334d3c..e22e96e00 100644 --- a/src/lib/block/aes/aes.h +++ b/src/lib/block/aes/aes.h @@ -23,6 +23,7 @@ class BOTAN_DLL AES_128 final : public Block_Cipher_Fixed_Params<16, 16> void clear() override; + const char* provider() const override; std::string name() const override { return "AES-128"; } BlockCipher* clone() const override { return new AES_128; } private: @@ -55,6 +56,7 @@ class BOTAN_DLL AES_192 final : public Block_Cipher_Fixed_Params<16, 24> void clear() override; + const char* provider() const override; std::string name() const override { return "AES-192"; } BlockCipher* clone() const override { return new AES_192; } private: @@ -87,6 +89,8 @@ class BOTAN_DLL AES_256 final : public Block_Cipher_Fixed_Params<16, 32> void clear() override; + const char* provider() const override; + std::string name() const override { return "AES-256"; } BlockCipher* clone() const override { return new AES_256; } private: diff --git a/src/lib/block/block_cipher.h b/src/lib/block/block_cipher.h index 0f4c2c1c5..68fc0f487 100644 --- a/src/lib/block/block_cipher.h +++ b/src/lib/block/block_cipher.h @@ -10,6 +10,7 @@ #include #include +#include namespace Botan { @@ -52,6 +53,13 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm return parallelism() * block_size() * BOTAN_BLOCK_CIPHER_PAR_MULT; } + /** + * @return provider information about this implementation. Default is "base", + * might also return "sse2", "avx2", "openssl", or some other arbitrary string. + * The return value is guaranteed to point to a string literal constant. + */ + virtual const char* provider() const { return "base"; } + /** * Encrypt a block. * @param in The plaintext block to be encrypted as a byte array. diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp index db55c5c26..8616b7765 100644 --- a/src/lib/block/idea/idea.cpp +++ b/src/lib/block/idea/idea.cpp @@ -109,6 +109,18 @@ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52]) } +const char* IDEA::provider() const + { +#if defined(BOTAN_HAS_IDEA_SSE2) + if(CPUID::has_sse2()) + { + return "sse2"; + } +#endif + + return "base"; + } + /* * IDEA Encryption */ diff --git a/src/lib/block/idea/idea.h b/src/lib/block/idea/idea.h index 063ec65c4..4a72685c8 100644 --- a/src/lib/block/idea/idea.h +++ b/src/lib/block/idea/idea.h @@ -22,6 +22,8 @@ class BOTAN_DLL IDEA final : public Block_Cipher_Fixed_Params<8, 16> void decrypt_n(const byte in[], byte out[], size_t blocks) const override; void clear() override; + + const char* provider() const override; std::string name() const override { return "IDEA"; } BlockCipher* clone() const override { return new IDEA; } private: diff --git a/src/lib/block/noekeon/noekeon.cpp b/src/lib/block/noekeon/noekeon.cpp index 5e7c0229e..fbafe092e 100644 --- a/src/lib/block/noekeon/noekeon.cpp +++ b/src/lib/block/noekeon/noekeon.cpp @@ -73,6 +73,18 @@ inline void gamma(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3) } +const char* Noekeon::provider() const + { +#if defined(BOTAN_HAS_NOEKEON_SIMD) + if(CPUID::has_simd_32()) + { + return "simd"; + } +#endif + + return "base"; + } + /* * Noekeon Round Constants */ diff --git a/src/lib/block/noekeon/noekeon.h b/src/lib/block/noekeon/noekeon.h index 30c15a001..31069eb75 100644 --- a/src/lib/block/noekeon/noekeon.h +++ b/src/lib/block/noekeon/noekeon.h @@ -21,6 +21,7 @@ class BOTAN_DLL Noekeon final : public Block_Cipher_Fixed_Params<16, 16> void encrypt_n(const byte in[], byte out[], size_t blocks) const override; void decrypt_n(const byte in[], byte out[], size_t blocks) const override; + const char* provider() const override; void clear() override; std::string name() const override { return "Noekeon"; } BlockCipher* clone() const override { return new Noekeon; } diff --git a/src/lib/block/serpent/serpent.cpp b/src/lib/block/serpent/serpent.cpp index 1e3699914..f2a6035f1 100644 --- a/src/lib/block/serpent/serpent.cpp +++ b/src/lib/block/serpent/serpent.cpp @@ -231,4 +231,16 @@ void Serpent::clear() zap(m_round_key); } +const char* Serpent::provider() const + { +#if defined(BOTAN_HAS_SERPENT_SIMD) + if(CPUID::has_simd_32()) + { + return "simd"; + } +#endif + + return "base"; + } + } diff --git a/src/lib/block/serpent/serpent.h b/src/lib/block/serpent/serpent.h index 8f854678a..72c26d452 100644 --- a/src/lib/block/serpent/serpent.h +++ b/src/lib/block/serpent/serpent.h @@ -23,6 +23,7 @@ class BOTAN_DLL Serpent final : public Block_Cipher_Fixed_Params<16, 16, 32, 8> void decrypt_n(const byte in[], byte out[], size_t blocks) const override; void clear() override; + const char* provider() const override; std::string name() const override { return "Serpent"; } BlockCipher* clone() const override { return new Serpent; } diff --git a/src/lib/block/threefish/threefish.cpp b/src/lib/block/threefish/threefish.cpp index 33b3e25c8..4ba834c94 100644 --- a/src/lib/block/threefish/threefish.cpp +++ b/src/lib/block/threefish/threefish.cpp @@ -98,6 +98,18 @@ void Threefish_512::skein_feedfwd(const secure_vector& M, m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; } +const char* Threefish_512::provider() const + { +#if defined(BOTAN_HAS_THREEFISH_512_AVX2) + if(CPUID::has_avx2()) + { + return "avx2"; + } +#endif + + return "base"; + } + void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); diff --git a/src/lib/block/threefish/threefish.h b/src/lib/block/threefish/threefish.h index 270e71354..230c742f3 100644 --- a/src/lib/block/threefish/threefish.h +++ b/src/lib/block/threefish/threefish.h @@ -24,6 +24,7 @@ class BOTAN_DLL Threefish_512 final : public Block_Cipher_Fixed_Params<64, 64> void set_tweak(const byte tweak[], size_t len); void clear() override; + const char* provider() const override; std::string name() const override { return "Threefish-512"; } BlockCipher* clone() const override { return new Threefish_512; } protected: diff --git a/src/lib/hash/hash.h b/src/lib/hash/hash.h index ac1c22a65..0f35685d4 100644 --- a/src/lib/hash/hash.h +++ b/src/lib/hash/hash.h @@ -40,6 +40,13 @@ class BOTAN_DLL HashFunction : public Buffered_Computation */ virtual HashFunction* clone() const = 0; + /** + * @return provider information about this implementation. Default is "base", + * might also return "sse2", "avx2", "openssl", or some other arbitrary string. + * The return value is guaranteed to point to a string literal constant. + */ + virtual const char* provider() const { return "base"; } + HashFunction(); virtual ~HashFunction(); diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h index fe3388f3b..1fbb36824 100644 --- a/src/lib/mac/mac.h +++ b/src/lib/mac/mac.h @@ -51,6 +51,14 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation, * Get a new object representing the same algorithm as *this */ virtual MessageAuthenticationCode* clone() const = 0; + + /** + * @return provider information about this implementation. Default is "base", + * might also return "sse2", "avx2", "openssl", or some other arbitrary string. + * The return value is guaranteed to point to a string literal constant. + */ + virtual const char* provider() const { return "base"; } + }; typedef MessageAuthenticationCode MAC; diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index e23551cb4..590c0d0ce 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -185,6 +185,16 @@ std::string GCM_Mode::name() const return (m_cipher_name + "/GCM"); } +const char* GCM_Mode::provider() const + { +#if defined(BOTAN_HAS_GCM_CLMUL) + if(CPUID::has_clmul()) + return "clmul"; +#endif + + return "base"; + } + size_t GCM_Mode::update_granularity() const { return m_BS; diff --git a/src/lib/modes/aead/gcm/gcm.h b/src/lib/modes/aead/gcm/gcm.h index ba0d6cad8..f0176f36a 100644 --- a/src/lib/modes/aead/gcm/gcm.h +++ b/src/lib/modes/aead/gcm/gcm.h @@ -36,6 +36,8 @@ class BOTAN_DLL GCM_Mode : public AEAD_Mode size_t tag_size() const override { return m_tag_size; } void clear() override; + + const char* provider() const override; protected: GCM_Mode(BlockCipher* cipher, size_t tag_size); diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h index 73a5f7d96..fa4c0aa8d 100644 --- a/src/lib/modes/cipher_mode.h +++ b/src/lib/modes/cipher_mode.h @@ -113,14 +113,6 @@ class BOTAN_DLL Cipher_Mode */ virtual bool valid_nonce_length(size_t nonce_len) const = 0; - /** - * Return some short name describing the provider of this tranformation. - * Useful in cases where multiple implementations are available (eg, - * different implementations of AES). Default "core" is used for the - * 'standard' implementation included in the library. - */ - virtual std::string provider() const { return "core"; } - virtual std::string name() const = 0; virtual void clear() = 0; @@ -174,6 +166,13 @@ class BOTAN_DLL Cipher_Mode key_schedule(key, length); } + /** + * @return provider information about this implementation. Default is "base", + * might also return "sse2", "avx2", "openssl", or some other arbitrary string. + * The return value is guaranteed to point to a string literal constant. + */ + virtual const char* provider() const { return "base"; } + private: virtual void key_schedule(const byte key[], size_t length) = 0; }; diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp index c868e8977..d09fdb82b 100644 --- a/src/lib/prov/openssl/openssl_block.cpp +++ b/src/lib/prov/openssl/openssl_block.cpp @@ -25,6 +25,7 @@ class OpenSSL_BlockCipher : public BlockCipher ~OpenSSL_BlockCipher(); void clear() override; + const char* provider() const override { return "openssl"; } std::string name() const override { return m_cipher_name; } BlockCipher* clone() const override; diff --git a/src/lib/prov/openssl/openssl_hash.cpp b/src/lib/prov/openssl/openssl_hash.cpp index c14c551e4..fa31d36c8 100644 --- a/src/lib/prov/openssl/openssl_hash.cpp +++ b/src/lib/prov/openssl/openssl_hash.cpp @@ -23,6 +23,7 @@ class OpenSSL_HashFunction : public HashFunction EVP_DigestInit_ex(&m_md, algo, nullptr); } + const char* provider() const override { return "openssl"; } std::string name() const override { return m_name; } HashFunction* clone() const override diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp index d6246e4ab..50148f09a 100644 --- a/src/lib/prov/openssl/openssl_rc4.cpp +++ b/src/lib/prov/openssl/openssl_rc4.cpp @@ -24,6 +24,8 @@ class OpenSSL_RC4 : public StreamCipher public: void clear() override { clear_mem(&m_rc4, 1); } + const char* provider() const override { return "openssl"; } + std::string name() const override { switch(m_skip) diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index c35363112..66d7ad90d 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -17,6 +17,18 @@ ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds"); } +const char* ChaCha::provider() const + { +#if defined(BOTAN_HAS_CHACHA_SSE2) + if(CPUID::has_sse2()) + { + return "sse2"; + } +#endif + + return "base"; + } + //static void ChaCha::chacha_x4(byte output[64*4], u32bit input[16], size_t rounds) { diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index 7e9e54768..19ed6d25f 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -26,6 +26,8 @@ class BOTAN_DLL ChaCha final : public StreamCipher */ ChaCha(size_t rounds = 20); + const char* provider() const override; + void cipher(const byte in[], byte out[], size_t length) override; void set_iv(const byte iv[], size_t iv_len) override; diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h index e08bee0ce..e41cdaa6d 100644 --- a/src/lib/stream/stream_cipher.h +++ b/src/lib/stream/stream_cipher.h @@ -86,6 +86,13 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm */ virtual void seek(u64bit offset) = 0; + /** + * @return provider information about this implementation. Default is "base", + * might also return "sse2", "avx2", "openssl", or some other arbitrary string. + * The return value is guaranteed to point to a string literal constant. + */ + virtual const char* provider() const { return "base"; } + StreamCipher(); virtual ~StreamCipher(); }; 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 cipher(Botan::BlockCipher::create(algo, provider)); + std::unique_ptr 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 hash(Botan::HashFunction::create(algo, provider)); + std::unique_ptr 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 mac(Botan::MessageAuthenticationCode::create(algo, provider)); + std::unique_ptr 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 cipher(Botan::StreamCipher::create(algo, provider)); + std::unique_ptr 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 2e8a1e4de..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); diff --git a/src/tests/tests.h b/src/tests/tests.h index 43b9e0d3a..1ceb24f48 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -171,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); -- cgit v1.2.3 From 4266b51c35d7c0e86f513030ae4a5b28fdb9b824 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 16 Sep 2016 15:45:38 -0400 Subject: Add try/catch block at top-level test runner --- src/tests/main.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/tests') 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{r}; + } }; fut_results.push_back(std::async(std::launch::async, run_it)); -- cgit v1.2.3