diff options
author | Jack Lloyd <[email protected]> | 2016-09-15 09:16:46 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-09-15 09:25:49 -0400 |
commit | 04bf8dc51861bab37d6260de8b318dc71ea4bba7 (patch) | |
tree | 03cf4b8d607607444049bc2b9880abc4c1fc6a8e | |
parent | a7eba3629cc0d76444f5241fb4b9e8793ddb61cd (diff) |
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.
29 files changed, 178 insertions, 20 deletions
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 <botan/scan_name.h> #include <botan/sym_algo.h> +#include <string> namespace Botan { @@ -53,6 +54,13 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm } /** + * @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. * Must be of length block_size(). 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<u64bit>& 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<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 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); |