diff options
author | lloyd <[email protected]> | 2015-01-28 04:32:10 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2015-01-28 04:32:10 +0000 |
commit | 7b56f1bd570dc684ffd7c945dee0d9b5480354ff (patch) | |
tree | 0c50ad534280a292a1b76daee9a19b34cfd96367 /src/lib | |
parent | b8fa304ec981d273c45d7ef31705d65ccfb00cc1 (diff) |
Add a runtime map of string->func() which when called return
Transforms and BlockCiphers. Registration for all types is done at
startup but is very cheap as just a std::function and a std::map entry
are created, no actual objects are created until needed. This is a
huge improvement over Algorithm_Factory which used T::clone() as the
function and thus kept a prototype object of each type in memory.
Replace existing lookup mechanisms for ciphers, AEADs, and compression
to use the transform lookup. The existing Engine framework remains in
place for BlockCipher, but the engines now just call to the registry
instead of having hardcoded lookups.
s/Transformation/Transform/ with typedefs for compatability.
Remove lib/selftest code (for runtime selftesting): not the right approach.
Diffstat (limited to 'src/lib')
85 files changed, 810 insertions, 1293 deletions
diff --git a/src/lib/algo_base/algo_registry.cpp b/src/lib/algo_base/algo_registry.cpp new file mode 100644 index 000000000..c33b1b3c7 --- /dev/null +++ b/src/lib/algo_base/algo_registry.cpp @@ -0,0 +1,20 @@ +/* +* (C) 2014,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/transform.h> +#include <botan/algo_registry.h> + +namespace Botan { + +Transform* get_transform(const std::string& specstr, + const std::string& provider, + const std::string& dirstr) + { + Algo_Registry<Transform>::Spec spec(specstr, dirstr); + return Algo_Registry<Transform>::global_registry().make(spec, provider); + } + +} diff --git a/src/lib/algo_base/algo_registry.h b/src/lib/algo_base/algo_registry.h new file mode 100644 index 000000000..d40e9fc67 --- /dev/null +++ b/src/lib/algo_base/algo_registry.h @@ -0,0 +1,146 @@ +/* +* (C) 2014,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ALGO_REGISTRY_H__ +#define BOTAN_ALGO_REGISTRY_H__ + +#include <botan/types.h> +#include <functional> +#include <stdexcept> +#include <mutex> +#include <map> + +namespace Botan { + +size_t static_provider_weight(const std::string& prov_name); + +template<typename T> +class Algo_Registry + { + public: + typedef typename T::Spec Spec; + + typedef std::function<T* (const Spec&)> maker_fn; + + static Algo_Registry<T>& global_registry() + { + static Algo_Registry<T> g_registry; + return g_registry; + } + + void add(const std::string& name, const std::string& provider, maker_fn fn) + { + std::unique_lock<std::mutex> lock(m_mutex); + // TODO: check for duplicated registrations + m_maker_fns[name][provider] = fn; + } + + T* make(const Spec& spec, const std::string& provider = "") + { + maker_fn maker = find_maker(spec, provider); + + try + { + return maker(spec); + } + catch(std::exception& e) + { + throw std::runtime_error("Creating '" + spec.as_string() + "' failed: " + e.what()); + } + } + + class Add + { + public: + Add(const std::string& basename, maker_fn fn, const std::string& provider = "builtin") + { + Algo_Registry<T>::global_registry().add(basename, provider, fn); + } + + Add(bool cond, const std::string& basename, maker_fn fn, const std::string& provider) + { + if(cond) + Algo_Registry<T>::global_registry().add(basename, provider, fn); + } + }; + + private: + Algo_Registry() {} + + maker_fn find_maker(const Spec& spec, const std::string& provider) + { + const std::string basename = spec.algo_name(); + + std::unique_lock<std::mutex> lock(m_mutex); + auto providers = m_maker_fns.find(basename); + + if(providers != m_maker_fns.end() && !providers->second.empty()) + { + const std::map<std::string, maker_fn>& prov = providers->second; + + if(provider != "") + { + // find one explicit provider requested by user, or fail + auto i = prov.find(provider); + if(i != prov.end()) + return i->second; + } + else + { + if(prov.size() == 1) + { + return prov.begin()->second; + } + else if(prov.size() > 1) + { + // TODO choose best of available options (how?) + //throw std::runtime_error("multiple choice not implemented"); + return prov.begin()->second; + } + } + } + // Default result is a function producing a null pointer + return [](const Spec&) { return nullptr; }; + } + + std::mutex m_mutex; + std::map<std::string, std::map<std::string, maker_fn>> m_maker_fns; + }; + +template<typename T> T* +make_new_T(const typename Algo_Registry<T>::Spec&) { return new T; } + +template<typename T, size_t DEF_VAL> T* +make_new_T_1len(const typename Algo_Registry<T>::Spec& spec) + { + return new T(spec.arg_as_integer(0, DEF_VAL)); + } + +template<typename T> T* +make_new_T_1str(const typename Algo_Registry<T>::Spec& spec, const std::string& def) + { + return new T(spec.arg(0, def)); + } + +#define BOTAN_REGISTER_NAMED_T(T, namestr, type, maker) \ + namespace { Algo_Registry<T>::Add g_ ## type ## _reg(namestr, maker); } +#define BOTAN_REGISTER_T(T, name, maker) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, maker); } +#define BOTAN_REGISTER_T_NOARGS(T, name) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, make_new_T<name>); } +#define BOTAN_REGISTER_T_1LEN(T, name, def) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, make_new_T_1len<name, def>); } + +#define BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, T, type, name, provider) \ + namespace { Algo_Registry<T>::Add g_ ## type ## _reg(cond, name, make_new_T<type>, provider); } + +// TODO move elsewhere: +#define BOTAN_REGISTER_TRANSFORM(name, maker) BOTAN_REGISTER_T(Transform, name, maker) +#define BOTAN_REGISTER_TRANSFORM_NOARGS(name) BOTAN_REGISTER_T_NOARGS(Transform, name) + +} + +#endif diff --git a/src/lib/algo_base/scan_name.cpp b/src/lib/algo_base/scan_name.cpp index 063900aae..ad34e05c1 100644 --- a/src/lib/algo_base/scan_name.cpp +++ b/src/lib/algo_base/scan_name.cpp @@ -65,6 +65,11 @@ deref_aliases(const std::pair<size_t, std::string>& in) std::mutex SCAN_Name::s_alias_map_mutex; std::map<std::string, std::string> SCAN_Name::s_alias_map; +SCAN_Name::SCAN_Name(std::string algo_spec, const std::string& extra) : SCAN_Name(algo_spec) + { + alg_name += extra; + } + SCAN_Name::SCAN_Name(std::string algo_spec) { orig_algo_spec = algo_spec; @@ -73,7 +78,7 @@ SCAN_Name::SCAN_Name(std::string algo_spec) size_t level = 0; std::pair<size_t, std::string> accum = std::make_pair(level, ""); - std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; + const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; algo_spec = SCAN_Name::deref_alias(algo_spec); @@ -130,12 +135,9 @@ SCAN_Name::SCAN_Name(std::string algo_spec) } } -std::string SCAN_Name::algo_name_and_args() const +std::string SCAN_Name::all_arguments() const { std::string out; - - out = algo_name(); - if(arg_count()) { out += '('; @@ -146,16 +148,14 @@ std::string SCAN_Name::algo_name_and_args() const out += ','; } out += ')'; - } - return out; } std::string SCAN_Name::arg(size_t i) const { if(i >= arg_count()) - throw std::range_error("SCAN_Name::argument - i out of range"); + throw std::range_error("SCAN_Name::arg - i out of range"); return args[i]; } diff --git a/src/lib/algo_base/scan_name.h b/src/lib/algo_base/scan_name.h index eb64f94eb..82be8d49c 100644 --- a/src/lib/algo_base/scan_name.h +++ b/src/lib/algo_base/scan_name.h @@ -29,19 +29,29 @@ class BOTAN_DLL SCAN_Name SCAN_Name(std::string algo_spec); /** + * @param algo_spec A SCAN-format name + */ + SCAN_Name(std::string algo_spec, const std::string& extra); + + /** * @return original input string */ - std::string as_string() const { return orig_algo_spec; } + const std::string& as_string() const { return orig_algo_spec; } /** * @return algorithm name */ - std::string algo_name() const { return alg_name; } + const std::string& algo_name() const { return alg_name; } /** * @return algorithm name plus any arguments */ - std::string algo_name_and_args() const; + std::string algo_name_and_args() const { return algo_name() + all_arguments(); } + + /** + * @return all arguments + */ + std::string all_arguments() const; /** * @return number of arguments diff --git a/src/lib/algo_base/transform.h b/src/lib/algo_base/transform.h index 444622b74..75bd5004a 100644 --- a/src/lib/algo_base/transform.h +++ b/src/lib/algo_base/transform.h @@ -1,5 +1,5 @@ /* -* Transformations of data +* Transforms of data * (C) 2013 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) @@ -12,6 +12,7 @@ #include <botan/key_spec.h> #include <botan/exceptn.h> #include <botan/symkey.h> +#include <botan/scan_name.h> #include <string> #include <vector> @@ -20,9 +21,11 @@ namespace Botan { /** * Interface for general transformations on data */ -class BOTAN_DLL Transformation +class BOTAN_DLL Transform { public: + typedef SCAN_Name Spec; + /** * Begin processing a message. * @param nonce the per message nonce @@ -38,7 +41,7 @@ class BOTAN_DLL Transformation * @param nonce the per message nonce */ template<typename Alloc> - BOTAN_DEPRECATED("Use Transformation::start") + BOTAN_DEPRECATED("Use Transform::start") secure_vector<byte> start_vec(const std::vector<byte, Alloc>& nonce) { return start(&nonce[0], nonce.size()); @@ -120,10 +123,10 @@ class BOTAN_DLL Transformation virtual void clear() = 0; - virtual ~Transformation() {} + virtual ~Transform() {} }; -class BOTAN_DLL Keyed_Transform : public Transformation +class BOTAN_DLL Keyed_Transform : public Transform { public: /** @@ -168,6 +171,12 @@ class BOTAN_DLL Keyed_Transform : public Transformation virtual void key_schedule(const byte key[], size_t length) = 0; }; +typedef Transform Transformation; + +BOTAN_DLL Transform* get_transform(const std::string& specstr, + const std::string& provider = "", + const std::string& dirstr = ""); + } #endif diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp index 8180231ca..ff8c97b76 100644 --- a/src/lib/block/aes/aes.cpp +++ b/src/lib/block/aes/aes.cpp @@ -7,12 +7,15 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/aes.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(AES_128, "AES-128"); +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(AES_192, "AES-192"); +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(AES_256, "AES-256"); + namespace { const byte SE[256] = { diff --git a/src/lib/block/aes_ni/aes_ni.cpp b/src/lib/block/aes_ni/aes_ni.cpp index aa061b3c1..256895148 100644 --- a/src/lib/block/aes_ni/aes_ni.cpp +++ b/src/lib/block/aes_ni/aes_ni.cpp @@ -5,12 +5,17 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/aes_ni.h> -#include <botan/loadstor.h> +#include <botan/cpuid.h> #include <wmmintrin.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_128_NI, "AES-128", "aes_ni"); +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_192_NI, "AES-192", "aes_ni"); +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_256_NI, "AES-256", "aes_ni"); + namespace { __m128i aes_128_key_expansion(__m128i key, __m128i key_with_rcon) diff --git a/src/lib/block/aes_ssse3/aes_ssse3.cpp b/src/lib/block/aes_ssse3/aes_ssse3.cpp index 40f0a5c8e..6a8fb3ed8 100644 --- a/src/lib/block/aes_ssse3/aes_ssse3.cpp +++ b/src/lib/block/aes_ssse3/aes_ssse3.cpp @@ -10,11 +10,17 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/aes_ssse3.h> +#include <botan/cpuid.h> #include <tmmintrin.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_128_SSSE3, "AES-128", "ssse3"); +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_192_SSSE3, "AES-192", "ssse3"); +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_256_SSSE3, "AES-256", "ssse3"); + namespace { const __m128i low_nibs = _mm_set1_epi8(0x0F); diff --git a/src/lib/block/block_cipher.h b/src/lib/block/block_cipher.h index 19dbc8e57..73e67b790 100644 --- a/src/lib/block/block_cipher.h +++ b/src/lib/block/block_cipher.h @@ -8,6 +8,7 @@ #ifndef BOTAN_BLOCK_CIPHER_H__ #define BOTAN_BLOCK_CIPHER_H__ +#include <botan/scan_name.h> #include <botan/sym_algo.h> namespace Botan { @@ -18,6 +19,7 @@ namespace Botan { class BOTAN_DLL BlockCipher : public SymmetricAlgorithm { public: + typedef SCAN_Name Spec; /** * @return block size of this algorithm diff --git a/src/lib/block/blowfish/blowfish.cpp b/src/lib/block/blowfish/blowfish.cpp index d388f9d97..ece1a31fd 100644 --- a/src/lib/block/blowfish/blowfish.cpp +++ b/src/lib/block/blowfish/blowfish.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/blowfish.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Blowfish); + /* * Blowfish Encryption */ diff --git a/src/lib/block/camellia/camellia.cpp b/src/lib/block/camellia/camellia.cpp index 2ee4251d7..5f04c9d12 100644 --- a/src/lib/block/camellia/camellia.cpp +++ b/src/lib/block/camellia/camellia.cpp @@ -5,12 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/camellia.h> #include <botan/internal/camellia_sbox.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Camellia_128, "Camellia-128"); +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Camellia_192, "Camellia-192"); +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Camellia_256, "Camellia-256"); + namespace Camellia_F { namespace { diff --git a/src/lib/block/cascade/cascade.cpp b/src/lib/block/cascade/cascade.cpp index 98e862de9..6c0458265 100644 --- a/src/lib/block/cascade/cascade.cpp +++ b/src/lib/block/cascade/cascade.cpp @@ -5,10 +5,29 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> +#include <botan/algo_registry.h> #include <botan/cascade.h> namespace Botan { +namespace { + +Cascade_Cipher* make_cascade(const BlockCipher::Spec& spec) + { + auto& block_cipher = Algo_Registry<BlockCipher>::global_registry(); + std::unique_ptr<BlockCipher> c1(block_cipher.make(spec.arg(0))); + std::unique_ptr<BlockCipher> c2(block_cipher.make(spec.arg(1))); + + if(c1 && c2) + return new Cascade_Cipher(c1.release(), c2.release()); + return nullptr; + } + +} + +BOTAN_REGISTER_NAMED_T(BlockCipher, "Cascade", Cascade_Cipher, make_cascade); + void Cascade_Cipher::encrypt_n(const byte in[], byte out[], size_t blocks) const { diff --git a/src/lib/block/cast/cast128.cpp b/src/lib/block/cast/cast128.cpp index e28106c55..3ac54f5e8 100644 --- a/src/lib/block/cast/cast128.cpp +++ b/src/lib/block/cast/cast128.cpp @@ -5,13 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/cast128.h> #include <botan/internal/cast_sboxes.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(CAST_128, "CAST-128"); + namespace { /* diff --git a/src/lib/block/cast/cast256.cpp b/src/lib/block/cast/cast256.cpp index 8dc78c11e..bbb9894e7 100644 --- a/src/lib/block/cast/cast256.cpp +++ b/src/lib/block/cast/cast256.cpp @@ -5,13 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/cast256.h> #include <botan/internal/cast_sboxes.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(CAST_256, "CAST-256"); + namespace { /* diff --git a/src/lib/block/des/des.cpp b/src/lib/block/des/des.cpp index 3b6c2ee4a..2994b7cb2 100644 --- a/src/lib/block/des/des.cpp +++ b/src/lib/block/des/des.cpp @@ -8,12 +8,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/des.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(DES); +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(TripleDES); + namespace { /* diff --git a/src/lib/block/des/desx.cpp b/src/lib/block/des/desx.cpp index 2e5274932..92cfc83cc 100644 --- a/src/lib/block/des/desx.cpp +++ b/src/lib/block/des/desx.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/desx.h> -#include <botan/internal/xor_buf.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(DESX); + /* * DESX Encryption */ diff --git a/src/lib/block/gost_28147/gost_28147.cpp b/src/lib/block/gost_28147/gost_28147.cpp index f70072f22..90bf9328d 100644 --- a/src/lib/block/gost_28147/gost_28147.cpp +++ b/src/lib/block/gost_28147/gost_28147.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/gost_28147.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1STR(GOST_28147_89, "GOST-28147-89", "R3411_94_TestParam"); + byte GOST_28147_89_Params::sbox_entry(size_t row, size_t col) const { byte x = sboxes[4 * col + (row / 2)]; diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp index 2d282461d..fa98e3754 100644 --- a/src/lib/block/idea/idea.cpp +++ b/src/lib/block/idea/idea.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/idea.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(IDEA); + namespace { /* diff --git a/src/lib/block/idea_sse2/idea_sse2.cpp b/src/lib/block/idea_sse2/idea_sse2.cpp index 389fbdd2b..3dfd26860 100644 --- a/src/lib/block/idea_sse2/idea_sse2.cpp +++ b/src/lib/block/idea_sse2/idea_sse2.cpp @@ -5,11 +5,15 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/idea_sse2.h> +#include <botan/cpuid.h> #include <emmintrin.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_sse2(), IDEA_SSE2, "IDEA", "sse2"); + namespace { inline __m128i mul(__m128i X, u16bit K_16) diff --git a/src/lib/block/info.txt b/src/lib/block/info.txt index 70e2b2ca2..f10acaa86 100644 --- a/src/lib/block/info.txt +++ b/src/lib/block/info.txt @@ -3,3 +3,11 @@ define BLOCK_CIPHER 20131128 <requires> algo_base </requires> + +<header:public> +block_cipher.h +</header:public> + +<header:internal> +block_utils.h +</header:internal> diff --git a/src/lib/block/kasumi/kasumi.cpp b/src/lib/block/kasumi/kasumi.cpp index 53321e94d..d0233cf5c 100644 --- a/src/lib/block/kasumi/kasumi.cpp +++ b/src/lib/block/kasumi/kasumi.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/kasumi.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(KASUMI); + namespace { /* diff --git a/src/lib/block/lion/lion.cpp b/src/lib/block/lion/lion.cpp index 7e18eec56..420b92cdb 100644 --- a/src/lib/block/lion/lion.cpp +++ b/src/lib/block/lion/lion.cpp @@ -5,12 +5,36 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/lion.h> -#include <botan/internal/xor_buf.h> #include <botan/parsing.h> +#include <botan/libstate.h> namespace Botan { +namespace { + +Lion* make_lion(const BlockCipher::Spec& spec) + { + if(spec.arg_count_between(2, 3)) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + const HashFunction* hash = af.prototype_hash_function(spec.arg(0)); + const StreamCipher* stream_cipher = af.prototype_stream_cipher(spec.arg(1)); + + if(hash && stream_cipher) + { + const size_t block_size = spec.arg_as_integer(2, 1024); + return new Lion(hash->clone(), stream_cipher->clone(), block_size); + } + } + return nullptr; + } + +} + +BOTAN_REGISTER_NAMED_T(BlockCipher, "Lion", Lion, make_lion); + /* * Lion Encryption */ diff --git a/src/lib/block/mars/mars.cpp b/src/lib/block/mars/mars.cpp index 6821738dd..50f264861 100644 --- a/src/lib/block/mars/mars.cpp +++ b/src/lib/block/mars/mars.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/mars.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MARS); + namespace { /** diff --git a/src/lib/block/misty1/misty1.cpp b/src/lib/block/misty1/misty1.cpp index d6ffda945..23233e02f 100644 --- a/src/lib/block/misty1/misty1.cpp +++ b/src/lib/block/misty1/misty1.cpp @@ -5,12 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/misty1.h> -#include <botan/loadstor.h> #include <botan/parsing.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MISTY1); + namespace { static const byte MISTY1_SBOX_S7[128] = { @@ -257,14 +259,4 @@ void MISTY1::clear() zap(DK); } -/* -* MISTY1 Constructor -*/ -MISTY1::MISTY1(size_t rounds) - { - if(rounds != 8) - throw Invalid_Argument("MISTY1: Invalid number of rounds: " - + std::to_string(rounds)); - } - } diff --git a/src/lib/block/misty1/misty1.h b/src/lib/block/misty1/misty1.h index 17b617283..177c2c0b5 100644 --- a/src/lib/block/misty1/misty1.h +++ b/src/lib/block/misty1/misty1.h @@ -13,7 +13,7 @@ namespace Botan { /** -* MISTY1 +* MISTY1 with 8 rounds */ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16> { @@ -24,12 +24,6 @@ class BOTAN_DLL MISTY1 : public Block_Cipher_Fixed_Params<8, 16> void clear(); std::string name() const { return "MISTY1"; } BlockCipher* clone() const { return new MISTY1; } - - /** - * @param rounds the number of rounds. Must be 8 with the current - * implementation - */ - MISTY1(size_t rounds = 8); private: void key_schedule(const byte[], size_t); diff --git a/src/lib/block/noekeon/noekeon.cpp b/src/lib/block/noekeon/noekeon.cpp index aa593c95f..09a2f6c15 100644 --- a/src/lib/block/noekeon/noekeon.cpp +++ b/src/lib/block/noekeon/noekeon.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/noekeon.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Noekeon); + namespace { /* diff --git a/src/lib/block/noekeon_simd/noekeon_simd.cpp b/src/lib/block/noekeon_simd/noekeon_simd.cpp index 07fcf19ff..d5995ee1d 100644 --- a/src/lib/block/noekeon_simd/noekeon_simd.cpp +++ b/src/lib/block/noekeon_simd/noekeon_simd.cpp @@ -5,11 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/noekeon_simd.h> #include <botan/internal/simd_32.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(SIMD_32::enabled(), Noekeon_SIMD, "Noekeon", "simd32"); + /* * Noekeon's Theta Operation */ diff --git a/src/lib/block/rc2/rc2.cpp b/src/lib/block/rc2/rc2.cpp index 329b174e9..54f85ce00 100644 --- a/src/lib/block/rc2/rc2.cpp +++ b/src/lib/block/rc2/rc2.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/rc2.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(RC2); + /* * RC2 Encryption */ diff --git a/src/lib/block/rc5/rc5.cpp b/src/lib/block/rc5/rc5.cpp index 45067678f..27fa0e14d 100644 --- a/src/lib/block/rc5/rc5.cpp +++ b/src/lib/block/rc5/rc5.cpp @@ -5,14 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/rc5.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> #include <botan/parsing.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_1LEN(RC5, 12); + /* * RC5 Encryption */ diff --git a/src/lib/block/rc6/rc6.cpp b/src/lib/block/rc6/rc6.cpp index 183395310..e9aa5fe8b 100644 --- a/src/lib/block/rc6/rc6.cpp +++ b/src/lib/block/rc6/rc6.cpp @@ -5,13 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/rc6.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(RC6); + /* * RC6 Encryption */ diff --git a/src/lib/block/safer/safer_sk.cpp b/src/lib/block/safer/safer_sk.cpp index 390e5d9bb..f5996a986 100644 --- a/src/lib/block/safer/safer_sk.cpp +++ b/src/lib/block/safer/safer_sk.cpp @@ -5,15 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/safer_sk.h> -#include <botan/rotate.h> #include <botan/parsing.h> -#include <botan/rotate.h> namespace Botan { namespace { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1LEN(SAFER_SK, "SAFER-SK", 10); + const byte EXP[256] = { 0x01, 0x2D, 0xE2, 0x93, 0xBE, 0x45, 0x15, 0xAE, 0x78, 0x03, 0x87, 0xA4, 0xB8, 0x38, 0xCF, 0x3F, 0x08, 0x67, 0x09, 0x94, 0xEB, 0x26, 0xA8, 0x6B, diff --git a/src/lib/block/seed/seed.cpp b/src/lib/block/seed/seed.cpp index 833f9943f..316ef1e04 100644 --- a/src/lib/block/seed/seed.cpp +++ b/src/lib/block/seed/seed.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/seed.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(SEED); + /* * SEED G Function */ diff --git a/src/lib/block/serpent/serpent.cpp b/src/lib/block/serpent/serpent.cpp index f66cd2a32..0fd76ce8f 100644 --- a/src/lib/block/serpent/serpent.cpp +++ b/src/lib/block/serpent/serpent.cpp @@ -5,17 +5,18 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/serpent.h> #include <botan/internal/serpent_sbox.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Serpent); + namespace { /* -* Serpent's Linear Transformation +* Serpent's Linear Transform */ inline void transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { @@ -27,7 +28,7 @@ inline void transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) } /* -* Serpent's Inverse Linear Transformation +* Serpent's Inverse Linear Transform */ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) { diff --git a/src/lib/block/serpent_simd/serp_simd.cpp b/src/lib/block/serpent_simd/serp_simd.cpp index 1a379efca..fa7f419fe 100644 --- a/src/lib/block/serpent_simd/serp_simd.cpp +++ b/src/lib/block/serpent_simd/serp_simd.cpp @@ -5,13 +5,15 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/serp_simd.h> #include <botan/internal/serpent_sbox.h> #include <botan/internal/simd_32.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(SIMD_32::enabled(), Serpent_SIMD, "Serpent", "simd32"); + namespace { #define key_xor(round, B0, B1, B2, B3) \ diff --git a/src/lib/block/serpent_x86_32/serp_x86_32.cpp b/src/lib/block/serpent_x86_32/serp_x86_32.cpp index 5548e3496..3c326d084 100644 --- a/src/lib/block/serpent_x86_32/serp_x86_32.cpp +++ b/src/lib/block/serpent_x86_32/serp_x86_32.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/serp_x86_32.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Serpent_X86_32, "Serpent", "x86-32"); + extern "C" { /** diff --git a/src/lib/block/tea/tea.cpp b/src/lib/block/tea/tea.cpp index 01f342607..ef630f715 100644 --- a/src/lib/block/tea/tea.cpp +++ b/src/lib/block/tea/tea.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/tea.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(TEA); + /* * TEA Encryption */ diff --git a/src/lib/block/threefish/threefish.cpp b/src/lib/block/threefish/threefish.cpp index f6636615b..322f54881 100644 --- a/src/lib/block/threefish/threefish.cpp +++ b/src/lib/block/threefish/threefish.cpp @@ -5,12 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/threefish.h> -#include <botan/rotate.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Threefish_512, "Threefish-512"); + #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X0 += X4; \ @@ -223,6 +224,7 @@ void Threefish_512::set_tweak(const byte tweak[], size_t len) { if(len != 16) throw std::runtime_error("Unsupported twofish tweak length"); + m_T.resize(3); m_T[0] = load_le<u64bit>(tweak, 0); m_T[1] = load_le<u64bit>(tweak, 1); m_T[2] = m_T[0] ^ m_T[1]; @@ -238,6 +240,10 @@ void Threefish_512::key_schedule(const byte key[], size_t) m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^ m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; + + // Reset tweak to all zeros on key reset + m_T.resize(3); + zeroise(m_T); } void Threefish_512::clear() diff --git a/src/lib/block/threefish/threefish.h b/src/lib/block/threefish/threefish.h index 6020b8a28..373600885 100644 --- a/src/lib/block/threefish/threefish.h +++ b/src/lib/block/threefish/threefish.h @@ -26,9 +26,6 @@ class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64> void clear() override; std::string name() const override { return "Threefish-512"; } BlockCipher* clone() const override { return new Threefish_512; } - - Threefish_512() : m_T(3) {} - protected: const secure_vector<u64bit>& get_T() const { return m_T; } const secure_vector<u64bit>& get_K() const { return m_K; } diff --git a/src/lib/block/threefish_avx2/threefish_avx2.cpp b/src/lib/block/threefish_avx2/threefish_avx2.cpp index ee0ecde85..432059585 100644 --- a/src/lib/block/threefish_avx2/threefish_avx2.cpp +++ b/src/lib/block/threefish_avx2/threefish_avx2.cpp @@ -1,15 +1,19 @@ /* -* Threefish-512 +* Threefish-512 using AVX2 * (C) 2013 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/threefish_avx2.h> +#include <botan/cpuid.h> #include <immintrin.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_avx2(), Threefish_512_AVX2, "Threefish-512", "avx2"); + namespace { inline void interleave_epi64(__m256i& X0, __m256i& X1) diff --git a/src/lib/block/threefish_avx2/threefish_avx2.h b/src/lib/block/threefish_avx2/threefish_avx2.h index ba24f114f..d851ff0dc 100644 --- a/src/lib/block/threefish_avx2/threefish_avx2.h +++ b/src/lib/block/threefish_avx2/threefish_avx2.h @@ -20,6 +20,12 @@ class BOTAN_DLL Threefish_512_AVX2 : public Threefish_512 private: 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; + + /* TODO: + void skein_feedfwd(const secure_vector<u64bit>& M, + const secure_vector<u64bit>& T) override; + */ + BlockCipher* clone() const override { return new Threefish_512_AVX2; } }; diff --git a/src/lib/block/twofish/twofish.cpp b/src/lib/block/twofish/twofish.cpp index ffdf4b198..43ea41bfd 100644 --- a/src/lib/block/twofish/twofish.cpp +++ b/src/lib/block/twofish/twofish.cpp @@ -8,12 +8,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/twofish.h> -#include <botan/loadstor.h> -#include <botan/rotate.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Twofish); + /* * Twofish Encryption */ diff --git a/src/lib/block/xtea/xtea.cpp b/src/lib/block/xtea/xtea.cpp index 59060dff7..9fe265457 100644 --- a/src/lib/block/xtea/xtea.cpp +++ b/src/lib/block/xtea/xtea.cpp @@ -5,11 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/xtea.h> -#include <botan/loadstor.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(XTEA); + namespace { void xtea_encrypt_4(const byte in[32], byte out[32], const u32bit EK[64]) diff --git a/src/lib/block/xtea_simd/xtea_simd.cpp b/src/lib/block/xtea_simd/xtea_simd.cpp index 87c7a20bf..6fd2f94c7 100644 --- a/src/lib/block/xtea_simd/xtea_simd.cpp +++ b/src/lib/block/xtea_simd/xtea_simd.cpp @@ -5,12 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/block_utils.h> #include <botan/xtea_simd.h> -#include <botan/loadstor.h> #include <botan/internal/simd_32.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(SIMD_32::enabled(), XTEA_SIMD, "XTEA", "simd32"); + namespace { void xtea_encrypt_8(const byte in[64], byte out[64], const u32bit EK[64]) diff --git a/src/lib/compression/bzip2/bzip2.cpp b/src/lib/compression/bzip2/bzip2.cpp index 471635e3e..2d1617bce 100644 --- a/src/lib/compression/bzip2/bzip2.cpp +++ b/src/lib/compression/bzip2/bzip2.cpp @@ -15,6 +15,8 @@ namespace Botan { +BOTAN_REGISTER_COMPRESSION(Bzip2_Compression, Bzip2_Decompression); + namespace { class Bzip2_Stream : public Zlib_Style_Stream<bz_stream, char> diff --git a/src/lib/compression/comp_util.h b/src/lib/compression/comp_util.h index 6e1ee1671..963eae642 100644 --- a/src/lib/compression/comp_util.h +++ b/src/lib/compression/comp_util.h @@ -9,6 +9,7 @@ #define BOTAN_COMPRESSION_UTILS_H__ #include <botan/compression.h> +#include <botan/algo_registry.h> #include <memory> #include <unordered_map> @@ -84,6 +85,10 @@ class Zlib_Style_Stream : public Compression_Stream std::unique_ptr<Compression_Alloc_Info> m_allocs; }; +#define BOTAN_REGISTER_COMPRESSION(C, D) \ + BOTAN_REGISTER_T_1LEN(Transform, C, 9) \ + BOTAN_REGISTER_T_NOARGS(Transform, D) + } #endif diff --git a/src/lib/compression/compression.cpp b/src/lib/compression/compression.cpp index 428271e9a..e5221aba6 100644 --- a/src/lib/compression/compression.cpp +++ b/src/lib/compression/compression.cpp @@ -6,67 +6,42 @@ */ #include <botan/compression.h> - -#if defined(BOTAN_HAS_ZLIB_TRANSFORM) - #include <botan/zlib.h> -#endif - -#if defined(BOTAN_HAS_BZIP2_TRANSFORM) - #include <botan/bzip2.h> -#endif - -#if defined(BOTAN_HAS_LZMA_TRANSFORM) - #include <botan/lzma.h> -#endif +#include <botan/algo_registry.h> namespace Botan { -Compressor_Transformation* make_compressor(const std::string& type, size_t level) +Transform* make_compressor(const std::string& type, size_t level) { -#if defined(BOTAN_HAS_ZLIB_TRANSFORM) + const std::string comp_suffix = "_Compression(" + std::to_string(level) + ")"; + if(type == "zlib") - return new Zlib_Compression(level); + return get_transform("Zlib" + comp_suffix); if(type == "deflate") - return new Deflate_Compression(level); + return get_transform("Deflate" + comp_suffix); if(type == "gzip" || type == "gz") - return new Gzip_Compression(level); -#endif - -#if defined(BOTAN_HAS_BZIP2_TRANSFORM) + return get_transform("Gzip" + comp_suffix); if(type == "bzip2" || type == "bz2") - return new Bzip2_Compression(level); -#endif - -#if defined(BOTAN_HAS_LZMA_TRANSFORM) + return get_transform("Bzip2", comp_suffix); if(type == "lzma" || type == "xz") - return new LZMA_Compression(level); -#endif + return get_transform("LZMA", comp_suffix); - throw std::runtime_error("Unknown compression type " + type); + return nullptr; } -Compressor_Transformation* make_decompressor(const std::string& type) +Transform* make_decompressor(const std::string& type) { -#if defined(BOTAN_HAS_ZLIB_TRANSFORM) if(type == "zlib") - return new Zlib_Decompression; + return get_transform("Zlib_Decompression"); if(type == "deflate") - return new Deflate_Decompression; + return get_transform("Deflate_Decompression"); if(type == "gzip" || type == "gz") - return new Gzip_Decompression; -#endif - -#if defined(BOTAN_HAS_BZIP2_TRANSFORM) + return get_transform("Gzip_Decompression"); if(type == "bzip2" || type == "bz2") - return new Bzip2_Decompression; -#endif - -#if defined(BOTAN_HAS_LZMA_TRANSFORM) + return get_transform("Bzip2_Decompression"); if(type == "lzma" || type == "xz") - return new LZMA_Decompression; -#endif + return get_transform("LZMA_Decompression"); - throw std::runtime_error("Unknown compression type " + type); + return nullptr; } void Stream_Compression::clear() diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h index b38d94f64..f70252cbe 100644 --- a/src/lib/compression/compression.h +++ b/src/lib/compression/compression.h @@ -12,7 +12,7 @@ namespace Botan { -class BOTAN_DLL Compressor_Transformation : public Transformation +class BOTAN_DLL Compressor_Transform : public Transform { public: size_t update_granularity() const override { return 1; } @@ -32,8 +32,8 @@ class BOTAN_DLL Compressor_Transformation : public Transformation } }; -BOTAN_DLL Compressor_Transformation* make_compressor(const std::string& type, size_t level); -BOTAN_DLL Compressor_Transformation* make_decompressor(const std::string& type); +BOTAN_DLL Transform* make_compressor(const std::string& type, size_t level); +BOTAN_DLL Transform* make_decompressor(const std::string& type); class Compression_Stream { @@ -55,7 +55,7 @@ class Compression_Stream virtual bool run(u32bit flags) = 0; }; -class BOTAN_DLL Stream_Compression : public Compressor_Transformation +class BOTAN_DLL Stream_Compression : public Compressor_Transform { public: void update(secure_vector<byte>& buf, size_t offset = 0) override; @@ -76,7 +76,7 @@ class BOTAN_DLL Stream_Compression : public Compressor_Transformation std::unique_ptr<Compression_Stream> m_stream; }; -class BOTAN_DLL Stream_Decompression : public Compressor_Transformation +class BOTAN_DLL Stream_Decompression : public Compressor_Transform { public: void update(secure_vector<byte>& buf, size_t offset = 0) override; diff --git a/src/lib/compression/lzma/lzma.cpp b/src/lib/compression/lzma/lzma.cpp index 0aadf1513..69d73a3a1 100644 --- a/src/lib/compression/lzma/lzma.cpp +++ b/src/lib/compression/lzma/lzma.cpp @@ -14,6 +14,8 @@ namespace Botan { +BOTAN_REGISTER_COMPRESSION(LZMA_Compression, LZMA_Decompression); + namespace { class LZMA_Stream : public Zlib_Style_Stream<lzma_stream, byte> diff --git a/src/lib/compression/zlib/zlib.cpp b/src/lib/compression/zlib/zlib.cpp index 8c94e4331..24e8721e3 100644 --- a/src/lib/compression/zlib/zlib.cpp +++ b/src/lib/compression/zlib/zlib.cpp @@ -14,6 +14,10 @@ namespace Botan { +BOTAN_REGISTER_COMPRESSION(Zlib_Compression, Zlib_Decompression); +BOTAN_REGISTER_COMPRESSION(Gzip_Compression, Gzip_Decompression); +BOTAN_REGISTER_COMPRESSION(Deflate_Compression, Deflate_Decompression); + namespace { class Zlib_Stream : public Zlib_Style_Stream<z_stream, Bytef> diff --git a/src/lib/engine/aes_isa_eng/aes_isa_engine.cpp b/src/lib/engine/aes_isa_eng/aes_isa_engine.cpp index c73eefcd3..d581b65ad 100644 --- a/src/lib/engine/aes_isa_eng/aes_isa_engine.cpp +++ b/src/lib/engine/aes_isa_eng/aes_isa_engine.cpp @@ -6,11 +6,7 @@ */ #include <botan/internal/aes_isa_engine.h> -#include <botan/cpuid.h> - -#if defined(BOTAN_HAS_AES_NI) - #include <botan/aes_ni.h> -#endif +#include <botan/algo_registry.h> namespace Botan { @@ -18,17 +14,8 @@ BlockCipher* AES_ISA_Engine::find_block_cipher(const SCAN_Name& request, Algorithm_Factory&) const { -#if defined(BOTAN_HAS_AES_NI) - if(CPUID::has_aes_ni()) - { - if(request.algo_name() == "AES-128") - return new AES_128_NI; - if(request.algo_name() == "AES-192") - return new AES_192_NI; - if(request.algo_name() == "AES-256") - return new AES_256_NI; - } -#endif + if(BlockCipher* c = Algo_Registry<BlockCipher>::global_registry().make(request, "aes_ni")) + return c; return nullptr; } diff --git a/src/lib/engine/core_engine/core_modes.cpp b/src/lib/engine/core_engine/core_modes.cpp index 1d96e581d..02a55bcd6 100644 --- a/src/lib/engine/core_engine/core_modes.cpp +++ b/src/lib/engine/core_engine/core_modes.cpp @@ -11,22 +11,7 @@ #include <botan/algo_factory.h> #include <botan/mode_pad.h> #include <botan/transform_filter.h> - -#if defined(BOTAN_HAS_MODE_CFB) - #include <botan/cfb.h> -#endif - -#if defined(BOTAN_HAS_MODE_ECB) - #include <botan/ecb.h> -#endif - -#if defined(BOTAN_HAS_MODE_CBC) - #include <botan/cbc.h> -#endif - -#if defined(BOTAN_HAS_MODE_XTS) - #include <botan/xts.h> -#endif +#include <botan/cipher_mode.h> #if defined(BOTAN_HAS_OFB) #include <botan/ofb.h> @@ -36,194 +21,8 @@ #include <botan/ctr.h> #endif -#if defined(BOTAN_HAS_AEAD_FILTER) - -#include <botan/aead_filt.h> - -#if defined(BOTAN_HAS_AEAD_CCM) - #include <botan/ccm.h> -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - #include <botan/eax.h> -#endif - -#if defined(BOTAN_HAS_AEAD_OCB) - #include <botan/ocb.h> -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - #include <botan/gcm.h> -#endif - -#endif - namespace Botan { -namespace { - -/** -* Get a block cipher padding method by name -*/ -BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec, - const std::string& def_if_empty) - { -#if defined(BOTAN_HAS_CIPHER_MODE_PADDING) - if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding")) - return new Null_Padding; - - if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7")) - return new PKCS7_Padding; - - if(algo_spec == "OneAndZeros") - return new OneAndZeros_Padding; - - if(algo_spec == "X9.23") - return new ANSI_X923_Padding; - -#endif - - throw Algorithm_Not_Found(algo_spec); - } - -} - -Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher, - Cipher_Dir direction, - const std::string& mode, - const std::string& padding) - { -#if defined(BOTAN_HAS_OFB) - if(mode == "OFB") - return new StreamCipher_Filter(new OFB(block_cipher->clone())); -#endif - -#if defined(BOTAN_HAS_CTR_BE) - if(mode == "CTR-BE") - return new StreamCipher_Filter(new CTR_BE(block_cipher->clone())); -#endif - -#if defined(BOTAN_HAS_MODE_ECB) - if(mode == "ECB" || mode == "") - { - if(direction == ENCRYPTION) - return new Transformation_Filter( - new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding"))); - else - return new Transformation_Filter( - new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding"))); - } -#endif - - if(mode == "CBC") - { -#if defined(BOTAN_HAS_MODE_CBC) - if(padding == "CTS") - { - if(direction == ENCRYPTION) - return new Transformation_Filter(new CTS_Encryption(block_cipher->clone())); - else - return new Transformation_Filter(new CTS_Decryption(block_cipher->clone())); - } - - if(direction == ENCRYPTION) - return new Transformation_Filter( - new CBC_Encryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7"))); - else - return new Transformation_Filter( - new CBC_Decryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7"))); -#else - return nullptr; -#endif - } - -#if defined(BOTAN_HAS_MODE_XTS) - if(mode == "XTS") - { - if(direction == ENCRYPTION) - return new Transformation_Filter(new XTS_Encryption(block_cipher->clone())); - else - return new Transformation_Filter(new XTS_Decryption(block_cipher->clone())); - } -#endif - - if(mode.find("CFB") != std::string::npos || - mode.find("EAX") != std::string::npos || - mode.find("GCM") != std::string::npos || - mode.find("OCB") != std::string::npos || - mode.find("CCM") != std::string::npos) - { - std::vector<std::string> algo_info = parse_algorithm_name(mode); - const std::string mode_name = algo_info[0]; - - size_t bits = 8 * block_cipher->block_size(); - if(algo_info.size() > 1) - bits = to_u32bit(algo_info[1]); - -#if defined(BOTAN_HAS_MODE_CFB) - if(mode_name == "CFB") - { - if(direction == ENCRYPTION) - return new Transformation_Filter(new CFB_Encryption(block_cipher->clone(), bits)); - else - return new Transformation_Filter(new CFB_Decryption(block_cipher->clone(), bits)); - } -#endif - - if(bits % 8 != 0) - throw std::invalid_argument("AEAD interface does not support non-octet length tags"); - -#if defined(BOTAN_HAS_AEAD_FILTER) - - const size_t tag_size = bits / 8; - -#if defined(BOTAN_HAS_AEAD_CCM) - if(mode_name == "CCM") - { - const size_t L = (algo_info.size() == 3) ? to_u32bit(algo_info[2]) : 3; - if(direction == ENCRYPTION) - return new AEAD_Filter(new CCM_Encryption(block_cipher->clone(), tag_size, L)); - else - return new AEAD_Filter(new CCM_Decryption(block_cipher->clone(), tag_size, L)); - } -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - if(mode_name == "EAX") - { - if(direction == ENCRYPTION) - return new AEAD_Filter(new EAX_Encryption(block_cipher->clone(), tag_size)); - else - return new AEAD_Filter(new EAX_Decryption(block_cipher->clone(), tag_size)); - } -#endif - -#if defined(BOTAN_HAS_AEAD_OCB) - if(mode_name == "OCB") - { - if(direction == ENCRYPTION) - return new AEAD_Filter(new OCB_Encryption(block_cipher->clone(), tag_size)); - else - return new AEAD_Filter(new OCB_Decryption(block_cipher->clone(), tag_size)); - } -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - if(mode_name == "GCM") - { - if(direction == ENCRYPTION) - return new AEAD_Filter(new GCM_Encryption(block_cipher->clone(), tag_size)); - else - return new AEAD_Filter(new GCM_Decryption(block_cipher->clone(), tag_size)); - } -#endif - -#endif - } - - return nullptr; - } - /* * Get a cipher object */ @@ -253,27 +52,23 @@ Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec, throw Lookup_Error("Cipher specification '" + algo_spec + "' is missing mode identifier"); - std::string mode = algo_parts[1]; + const std::string mode = algo_parts[1]; - std::string padding; - if(algo_parts.size() == 3) - padding = algo_parts[2]; - else - padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; +#if defined(BOTAN_HAS_OFB) + if(mode == "OFB") + return new StreamCipher_Filter(new OFB(block_cipher->clone())); +#endif - if(mode == "ECB" && padding == "CTS") - return nullptr; - else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") - throw Invalid_Algorithm_Name(algo_spec); +#if defined(BOTAN_HAS_CTR_BE) + if(mode == "CTR-BE") + return new StreamCipher_Filter(new CTR_BE(block_cipher->clone())); +#endif - Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding); - if(filt) - return filt; + std::unique_ptr<Cipher_Mode> c(get_cipher_mode(algo_spec, direction)); + if(c) + return new Transform_Filter(c.release()); - if(padding != "NoPadding") - throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding); - else - throw Algorithm_Not_Found(cipher_name + "/" + mode); + throw Algorithm_Not_Found(algo_spec); } } diff --git a/src/lib/engine/core_engine/lookup_block.cpp b/src/lib/engine/core_engine/lookup_block.cpp index 703e578ac..98186403e 100644 --- a/src/lib/engine/core_engine/lookup_block.cpp +++ b/src/lib/engine/core_engine/lookup_block.cpp @@ -7,101 +7,7 @@ #include <botan/internal/core_engine.h> #include <botan/scan_name.h> -#include <botan/algo_factory.h> - -#if defined(BOTAN_HAS_AES) - #include <botan/aes.h> -#endif - -#if defined(BOTAN_HAS_BLOWFISH) - #include <botan/blowfish.h> -#endif - -#if defined(BOTAN_HAS_CAMELLIA) - #include <botan/camellia.h> -#endif - -#if defined(BOTAN_HAS_CAST) - #include <botan/cast128.h> - #include <botan/cast256.h> -#endif - -#if defined(BOTAN_HAS_CASCADE) - #include <botan/cascade.h> -#endif - -#if defined(BOTAN_HAS_DES) - #include <botan/des.h> - #include <botan/desx.h> -#endif - -#if defined(BOTAN_HAS_GOST_28147_89) - #include <botan/gost_28147.h> -#endif - -#if defined(BOTAN_HAS_IDEA) - #include <botan/idea.h> -#endif - -#if defined(BOTAN_HAS_KASUMI) - #include <botan/kasumi.h> -#endif - -#if defined(BOTAN_HAS_LION) - #include <botan/lion.h> -#endif - -#if defined(BOTAN_HAS_MARS) - #include <botan/mars.h> -#endif - -#if defined(BOTAN_HAS_MISTY1) - #include <botan/misty1.h> -#endif - -#if defined(BOTAN_HAS_NOEKEON) - #include <botan/noekeon.h> -#endif - -#if defined(BOTAN_HAS_RC2) - #include <botan/rc2.h> -#endif - -#if defined(BOTAN_HAS_RC5) - #include <botan/rc5.h> -#endif - -#if defined(BOTAN_HAS_RC6) - #include <botan/rc6.h> -#endif - -#if defined(BOTAN_HAS_SAFER) - #include <botan/safer_sk.h> -#endif - -#if defined(BOTAN_HAS_SEED) - #include <botan/seed.h> -#endif - -#if defined(BOTAN_HAS_SERPENT) - #include <botan/serpent.h> -#endif - -#if defined(BOTAN_HAS_TEA) - #include <botan/tea.h> -#endif - -#if defined(BOTAN_HAS_TWOFISH) - #include <botan/twofish.h> -#endif - -#if defined(BOTAN_HAS_THREEFISH_512) - #include <botan/threefish.h> -#endif - -#if defined(BOTAN_HAS_XTEA) - #include <botan/xtea.h> -#endif +#include <botan/algo_registry.h> namespace Botan { @@ -109,156 +15,10 @@ namespace Botan { * Look for an algorithm with this name */ BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request, - Algorithm_Factory& af) const + Algorithm_Factory&) const { - -#if defined(BOTAN_HAS_AES) - if(request.algo_name() == "AES-128") - return new AES_128; - if(request.algo_name() == "AES-192") - return new AES_192; - if(request.algo_name() == "AES-256") - return new AES_256; -#endif - -#if defined(BOTAN_HAS_BLOWFISH) - if(request.algo_name() == "Blowfish") - return new Blowfish; -#endif - -#if defined(BOTAN_HAS_CAMELLIA) - if(request.algo_name() == "Camellia-128") - return new Camellia_128; - if(request.algo_name() == "Camellia-192") - return new Camellia_192; - if(request.algo_name() == "Camellia-256") - return new Camellia_256; -#endif - -#if defined(BOTAN_HAS_CAST) - if(request.algo_name() == "CAST-128") - return new CAST_128; - if(request.algo_name() == "CAST-256") - return new CAST_256; -#endif - -#if defined(BOTAN_HAS_DES) - if(request.algo_name() == "DES") - return new DES; - if(request.algo_name() == "DESX") - return new DESX; - if(request.algo_name() == "TripleDES") - return new TripleDES; -#endif - -#if defined(BOTAN_HAS_GOST_28147_89) - if(request.algo_name() == "GOST-28147-89") - return new GOST_28147_89(request.arg(0, "R3411_94_TestParam")); -#endif - -#if defined(BOTAN_HAS_IDEA) - if(request.algo_name() == "IDEA") - return new IDEA; -#endif - -#if defined(BOTAN_HAS_KASUMI) - if(request.algo_name() == "KASUMI") - return new KASUMI; -#endif - -#if defined(BOTAN_HAS_MARS) - if(request.algo_name() == "MARS") - return new MARS; -#endif - -#if defined(BOTAN_HAS_MISTY1) - if(request.algo_name() == "MISTY1") - return new MISTY1(request.arg_as_integer(0, 8)); -#endif - -#if defined(BOTAN_HAS_NOEKEON) - if(request.algo_name() == "Noekeon") - return new Noekeon; -#endif - -#if defined(BOTAN_HAS_RC2) - if(request.algo_name() == "RC2") - return new RC2; -#endif - -#if defined(BOTAN_HAS_RC5) - if(request.algo_name() == "RC5") - return new RC5(request.arg_as_integer(0, 12)); -#endif - -#if defined(BOTAN_HAS_RC6) - if(request.algo_name() == "RC6") - return new RC6; -#endif - -#if defined(BOTAN_HAS_SAFER) - if(request.algo_name() == "SAFER-SK") - return new SAFER_SK(request.arg_as_integer(0, 10)); -#endif - -#if defined(BOTAN_HAS_SEED) - if(request.algo_name() == "SEED") - return new SEED; -#endif - -#if defined(BOTAN_HAS_SERPENT) - if(request.algo_name() == "Serpent") - return new Serpent; -#endif - -#if defined(BOTAN_HAS_TEA) - if(request.algo_name() == "TEA") - return new TEA; -#endif - -#if defined(BOTAN_HAS_TWOFISH) - if(request.algo_name() == "Twofish") - return new Twofish; -#endif - -#if defined(BOTAN_HAS_TWOFISH) - if(request.algo_name() == "Threefish-512") - return new Threefish_512; -#endif - -#if defined(BOTAN_HAS_XTEA) - if(request.algo_name() == "XTEA") - return new XTEA; -#endif - -#if defined(BOTAN_HAS_CASCADE) - if(request.algo_name() == "Cascade" && request.arg_count() == 2) - { - const BlockCipher* c1 = af.prototype_block_cipher(request.arg(0)); - const BlockCipher* c2 = af.prototype_block_cipher(request.arg(1)); - - if(c1 && c2) - return new Cascade_Cipher(c1->clone(), c2->clone()); - } -#endif - -#if defined(BOTAN_HAS_LION) - if(request.algo_name() == "Lion" && request.arg_count_between(2, 3)) - { - const size_t block_size = request.arg_as_integer(2, 1024); - - const HashFunction* hash = - af.prototype_hash_function(request.arg(0)); - - const StreamCipher* stream_cipher = - af.prototype_stream_cipher(request.arg(1)); - - if(!hash || !stream_cipher) - return nullptr; - - return new Lion(hash->clone(), stream_cipher->clone(), block_size); - } -#endif + if(BlockCipher* c = Algo_Registry<BlockCipher>::global_registry().make(request, "builtin")) + return c; return nullptr; } diff --git a/src/lib/engine/simd_engine/simd_engine.cpp b/src/lib/engine/simd_engine/simd_engine.cpp index af5f5d524..35d9cdad4 100644 --- a/src/lib/engine/simd_engine/simd_engine.cpp +++ b/src/lib/engine/simd_engine/simd_engine.cpp @@ -6,33 +6,9 @@ */ #include <botan/internal/simd_engine.h> -#include <botan/internal/simd_32.h> +#include <botan/algo_registry.h> #include <botan/cpuid.h> -#if defined(BOTAN_HAS_AES_SSSE3) - #include <botan/aes_ssse3.h> -#endif - -#if defined(BOTAN_HAS_SERPENT_SIMD) - #include <botan/serp_simd.h> -#endif - -#if defined(BOTAN_HAS_THREEFISH_512_AVX2) - #include <botan/threefish_avx2.h> -#endif - -#if defined(BOTAN_HAS_NOEKEON_SIMD) - #include <botan/noekeon_simd.h> -#endif - -#if defined(BOTAN_HAS_XTEA_SIMD) - #include <botan/xtea_simd.h> -#endif - -#if defined(BOTAN_HAS_IDEA_SSE2) - #include <botan/idea_sse2.h> -#endif - #if defined(BOTAN_HAS_SHA1_SSE2) #include <botan/sha1_sse2.h> #endif @@ -43,39 +19,19 @@ BlockCipher* SIMD_Engine::find_block_cipher(const SCAN_Name& request, Algorithm_Factory&) const { -#if defined(BOTAN_HAS_AES_SSSE3) - if(request.algo_name() == "AES-128" && CPUID::has_ssse3()) - return new AES_128_SSSE3; - if(request.algo_name() == "AES-192" && CPUID::has_ssse3()) - return new AES_192_SSSE3; - if(request.algo_name() == "AES-256" && CPUID::has_ssse3()) - return new AES_256_SSSE3; -#endif + auto& block_cipher = Algo_Registry<BlockCipher>::global_registry(); -#if defined(BOTAN_HAS_IDEA_SSE2) - if(request.algo_name() == "IDEA" && CPUID::has_sse2()) - return new IDEA_SSE2; -#endif + if(BlockCipher* c = block_cipher.make(request, "avx2")) + return c; -#if defined(BOTAN_HAS_NOEKEON_SIMD) - if(request.algo_name() == "Noekeon" && SIMD_32::enabled()) - return new Noekeon_SIMD; -#endif + if(BlockCipher* c = block_cipher.make(request, "ssse3")) + return c; -#if defined(BOTAN_HAS_THREEFISH_512_AVX2) - if(request.algo_name() == "Threefish-512" && CPUID::has_avx2()) - return new Threefish_512_AVX2; -#endif - -#if defined(BOTAN_HAS_SERPENT_SIMD) - if(request.algo_name() == "Serpent" && SIMD_32::enabled()) - return new Serpent_SIMD; -#endif + if(BlockCipher* c = block_cipher.make(request, "sse2")) + return c; -#if defined(BOTAN_HAS_XTEA_SIMD) - if(request.algo_name() == "XTEA" && SIMD_32::enabled()) - return new XTEA_SIMD; -#endif + if(BlockCipher* c = block_cipher.make(request, "simd32")) + return c; return nullptr; } diff --git a/src/lib/filters/aead_filt/aead_filt.h b/src/lib/filters/aead_filt/aead_filt.h index 52e448a7a..a97b580bd 100644 --- a/src/lib/filters/aead_filt/aead_filt.h +++ b/src/lib/filters/aead_filt/aead_filt.h @@ -16,10 +16,10 @@ namespace Botan { /** * Filter interface for AEAD Modes */ -class BOTAN_DLL AEAD_Filter : public Transformation_Filter +class BOTAN_DLL AEAD_Filter : public Transform_Filter { public: - AEAD_Filter(AEAD_Mode* aead) : Transformation_Filter(aead) {} + AEAD_Filter(AEAD_Mode* aead) : Transform_Filter(aead) {} /** * Set associated data that is not included in the ciphertext but diff --git a/src/lib/filters/comp_filter.cpp b/src/lib/filters/comp_filter.cpp index b7694ce24..4c5dfac68 100644 --- a/src/lib/filters/comp_filter.cpp +++ b/src/lib/filters/comp_filter.cpp @@ -20,9 +20,11 @@ Decompression_Filter::Decompression_Filter(const std::string& type) : { } -Compression_Decompression_Filter::Compression_Decompression_Filter(Compressor_Transformation* transform) : - m_transform(transform) +Compression_Decompression_Filter::Compression_Decompression_Filter(Transform* transform) { + m_transform.reset(dynamic_cast<Compressor_Transform*>(transform)); + if(!m_transform) + throw std::invalid_argument("Transform " + transform->name() + " is not a compressor"); } std::string Compression_Decompression_Filter::name() const diff --git a/src/lib/filters/comp_filter.h b/src/lib/filters/comp_filter.h index 7bfa5b568..2284d8963 100644 --- a/src/lib/filters/comp_filter.h +++ b/src/lib/filters/comp_filter.h @@ -12,7 +12,8 @@ namespace Botan { -class Compressor_Transformation; +class Transform; +class Compressor_Transform; /** * Filter interface for compression/decompression @@ -27,11 +28,11 @@ class BOTAN_DLL Compression_Decompression_Filter : public Filter std::string name() const override; protected: - Compression_Decompression_Filter(Compressor_Transformation* t); + Compression_Decompression_Filter(Transform* t); void flush(); private: - std::unique_ptr<Compressor_Transformation> m_transform; + std::unique_ptr<Compressor_Transform> m_transform; secure_vector<byte> m_buffer; }; diff --git a/src/lib/filters/transform_filter.cpp b/src/lib/filters/transform_filter.cpp index b084bf42e..1b709012e 100644 --- a/src/lib/filters/transform_filter.cpp +++ b/src/lib/filters/transform_filter.cpp @@ -1,5 +1,5 @@ /* -* Filter interface for Transformations +* Filter interface for Transforms * (C) 2013,2014 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) @@ -24,7 +24,7 @@ size_t choose_update_size(size_t update_granularity) } -Transformation_Filter::Transformation_Filter(Transformation* transform) : +Transform_Filter::Transform_Filter(Transform* transform) : Buffered_Filter(choose_update_size(transform->update_granularity()), transform->minimum_final_size()), m_nonce(transform->default_nonce_length() == 0), @@ -33,18 +33,18 @@ Transformation_Filter::Transformation_Filter(Transformation* transform) : { } -std::string Transformation_Filter::name() const +std::string Transform_Filter::name() const { return m_transform->name(); } -void Transformation_Filter::Nonce_State::update(const InitializationVector& iv) +void Transform_Filter::Nonce_State::update(const InitializationVector& iv) { m_nonce = unlock(iv.bits_of()); m_fresh_nonce = true; } -std::vector<byte> Transformation_Filter::Nonce_State::get() +std::vector<byte> Transform_Filter::Nonce_State::get() { BOTAN_ASSERT(m_fresh_nonce, "The nonce is fresh for this message"); @@ -53,47 +53,47 @@ std::vector<byte> Transformation_Filter::Nonce_State::get() return m_nonce; } -void Transformation_Filter::set_iv(const InitializationVector& iv) +void Transform_Filter::set_iv(const InitializationVector& iv) { m_nonce.update(iv); } -void Transformation_Filter::set_key(const SymmetricKey& key) +void Transform_Filter::set_key(const SymmetricKey& key) { if(Keyed_Transform* keyed = dynamic_cast<Keyed_Transform*>(m_transform.get())) keyed->set_key(key); else if(key.length() != 0) - throw std::runtime_error("Transformation " + name() + " does not accept keys"); + throw std::runtime_error("Transform " + name() + " does not accept keys"); } -Key_Length_Specification Transformation_Filter::key_spec() const +Key_Length_Specification Transform_Filter::key_spec() const { if(Keyed_Transform* keyed = dynamic_cast<Keyed_Transform*>(m_transform.get())) return keyed->key_spec(); return Key_Length_Specification(0); } -bool Transformation_Filter::valid_iv_length(size_t length) const +bool Transform_Filter::valid_iv_length(size_t length) const { return m_transform->valid_nonce_length(length); } -void Transformation_Filter::write(const byte input[], size_t input_length) +void Transform_Filter::write(const byte input[], size_t input_length) { Buffered_Filter::write(input, input_length); } -void Transformation_Filter::end_msg() +void Transform_Filter::end_msg() { Buffered_Filter::end_msg(); } -void Transformation_Filter::start_msg() +void Transform_Filter::start_msg() { send(m_transform->start(m_nonce.get())); } -void Transformation_Filter::buffered_block(const byte input[], size_t input_length) +void Transform_Filter::buffered_block(const byte input[], size_t input_length) { while(input_length) { @@ -109,7 +109,7 @@ void Transformation_Filter::buffered_block(const byte input[], size_t input_leng } } -void Transformation_Filter::buffered_final(const byte input[], size_t input_length) +void Transform_Filter::buffered_final(const byte input[], size_t input_length) { secure_vector<byte> buf(input, input + input_length); m_transform->finish(buf); diff --git a/src/lib/filters/transform_filter.h b/src/lib/filters/transform_filter.h index 86bd7580e..3dd68405b 100644 --- a/src/lib/filters/transform_filter.h +++ b/src/lib/filters/transform_filter.h @@ -1,12 +1,12 @@ /* -* Filter interface for Transformations +* Filter interface for Transforms * (C) 2013 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ -#ifndef BOTAN_TRANSFORMATION_FILTER_H__ -#define BOTAN_TRANSFORMATION_FILTER_H__ +#ifndef BOTAN_TRANSFORM_FILTER_H__ +#define BOTAN_TRANSFORM_FILTER_H__ #include <botan/transform.h> #include <botan/key_filt.h> @@ -15,13 +15,13 @@ namespace Botan { /** -* Filter interface for Transformations +* Filter interface for Transforms */ -class BOTAN_DLL Transformation_Filter : public Keyed_Filter, - private Buffered_Filter +class BOTAN_DLL Transform_Filter : public Keyed_Filter, + private Buffered_Filter { public: - Transformation_Filter(Transformation* t); + Transform_Filter(Transform* t); void set_iv(const InitializationVector& iv) override; @@ -34,9 +34,9 @@ class BOTAN_DLL Transformation_Filter : public Keyed_Filter, std::string name() const override; protected: - const Transformation& get_transform() const { return *m_transform; } + const Transform& get_transform() const { return *m_transform; } - Transformation& get_transform() { return *m_transform; } + Transform& get_transform() { return *m_transform; } private: void write(const byte input[], size_t input_length) override; @@ -59,10 +59,12 @@ class BOTAN_DLL Transformation_Filter : public Keyed_Filter, }; Nonce_State m_nonce; - std::unique_ptr<Transformation> m_transform; + std::unique_ptr<Transform> m_transform; secure_vector<byte> m_buffer; }; +typedef Transform_Filter Transformation_Filter; + } #endif diff --git a/src/lib/libstate/libstate.cpp b/src/lib/libstate/libstate.cpp index 6ce9c7eae..67ee7d358 100644 --- a/src/lib/libstate/libstate.cpp +++ b/src/lib/libstate/libstate.cpp @@ -14,10 +14,6 @@ #include <botan/internal/stl_util.h> #include <algorithm> -#if defined(BOTAN_HAS_SELFTESTS) - #include <botan/selftest.h> -#endif - #if defined(BOTAN_HAS_ENGINE_ASSEMBLER) #include <botan/internal/asm_engine.h> #endif @@ -99,10 +95,6 @@ void Library_State::initialize() m_sources = entropy_sources(); m_global_prng.reset(new Serialized_RNG()); - -#if defined(BOTAN_HAS_SELFTESTS) - confirm_startup_self_tests(algorithm_factory()); -#endif } } diff --git a/src/lib/modes/aead/aead.cpp b/src/lib/modes/aead/aead.cpp index b1cce73e0..1f2099d2e 100644 --- a/src/lib/modes/aead/aead.cpp +++ b/src/lib/modes/aead/aead.cpp @@ -1,135 +1,23 @@ /* -* Interface for AEAD modes -* (C) 2013 Jack Lloyd +* (C) 2013,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/aead.h> -#include <botan/block_cipher.h> -#include <botan/libstate.h> - -#if defined(BOTAN_HAS_AEAD_CCM) - #include <botan/ccm.h> -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - #include <botan/eax.h> -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - #include <botan/gcm.h> -#endif - -#if defined(BOTAN_HAS_AEAD_SIV) - #include <botan/siv.h> -#endif - -#if defined(BOTAN_HAS_AEAD_OCB) - #include <botan/ocb.h> -#endif - -#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) - #include <botan/chacha20poly1305.h> -#endif namespace Botan { AEAD_Mode* get_aead(const std::string& algo_spec, Cipher_Dir direction) { -#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) - if(algo_spec == "ChaCha20Poly1305") - { - if(direction == ENCRYPTION) - return new ChaCha20Poly1305_Encryption; - else - return new ChaCha20Poly1305_Decryption; - } -#endif - - Algorithm_Factory& af = global_state().algorithm_factory(); - - const std::vector<std::string> algo_parts = split_on(algo_spec, '/'); - if(algo_parts.empty()) - throw Invalid_Algorithm_Name(algo_spec); - - if(algo_parts.size() < 2) - return nullptr; - - const std::string cipher_name = algo_parts[0]; - const BlockCipher* cipher = af.prototype_block_cipher(cipher_name); - if(!cipher) - return nullptr; - - const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); - - if(mode_info.empty()) - return nullptr; - - const std::string mode_name = mode_info[0]; - - const size_t tag_size = (mode_info.size() > 1) ? to_u32bit(mode_info[1]) : cipher->block_size(); - -#if defined(BOTAN_HAS_AEAD_CCM) - if(mode_name == "CCM-8") - { - if(direction == ENCRYPTION) - return new CCM_Encryption(cipher->clone(), 8, 3); - else - return new CCM_Decryption(cipher->clone(), 8, 3); - } - - if(mode_name == "CCM" || mode_name == "CCM-8") - { - const size_t L = (mode_info.size() > 2) ? to_u32bit(mode_info[2]) : 3; - - if(direction == ENCRYPTION) - return new CCM_Encryption(cipher->clone(), tag_size, L); - else - return new CCM_Decryption(cipher->clone(), tag_size, L); - } -#endif - -#if defined(BOTAN_HAS_AEAD_EAX) - if(mode_name == "EAX") - { - if(direction == ENCRYPTION) - return new EAX_Encryption(cipher->clone(), tag_size); - else - return new EAX_Decryption(cipher->clone(), tag_size); - } -#endif - -#if defined(BOTAN_HAS_AEAD_SIV) - if(mode_name == "SIV") - { - BOTAN_ASSERT(tag_size == 16, "Valid tag size for SIV"); - if(direction == ENCRYPTION) - return new SIV_Encryption(cipher->clone()); - else - return new SIV_Decryption(cipher->clone()); - } -#endif - -#if defined(BOTAN_HAS_AEAD_GCM) - if(mode_name == "GCM") - { - if(direction == ENCRYPTION) - return new GCM_Encryption(cipher->clone(), tag_size); - else - return new GCM_Decryption(cipher->clone(), tag_size); - } -#endif + std::unique_ptr<Cipher_Mode> mode(get_cipher_mode(algo_spec, direction)); -#if defined(BOTAN_HAS_AEAD_OCB) - if(mode_name == "OCB") + if(AEAD_Mode* aead = dynamic_cast<AEAD_Mode*>(mode.get())) { - if(direction == ENCRYPTION) - return new OCB_Encryption(cipher->clone(), tag_size); - else - return new OCB_Decryption(cipher->clone(), tag_size); + mode.release(); + return aead; } -#endif return nullptr; } diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp index e0b247ddb..cc692e364 100644 --- a/src/lib/modes/aead/ccm/ccm.cpp +++ b/src/lib/modes/aead/ccm/ccm.cpp @@ -5,13 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ccm.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(CCM_Encryption, CCM_Decryption, 16, 3); + /* * CCM_Mode Constructor */ @@ -57,7 +58,7 @@ size_t CCM_Mode::update_granularity() const /* This value does not particularly matter as regardless CCM_Mode::update buffers all input, so in theory this could be 1. However as for instance - Transformation_Filter creates update_granularity() byte buffers, use a + Transform_Filter creates update_granularity() byte buffers, use a somewhat large size to avoid bouncing on a tiny buffer. */ return m_cipher->parallel_bytes(); diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp index 0961f1dc8..a278156eb 100644 --- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp +++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp @@ -5,14 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/chacha20poly1305.h> #include <botan/chacha.h> #include <botan/poly1305.h> -#include <botan/loadstor.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_TRANSFORM_NOARGS(ChaCha20Poly1305_Encryption); +BOTAN_REGISTER_TRANSFORM_NOARGS(ChaCha20Poly1305_Decryption); + bool ChaCha20Poly1305_Mode::valid_nonce_length(size_t n) const { return (n == 8 || n == 12); diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp index 289278a52..3b0c94416 100644 --- a/src/lib/modes/aead/eax/eax.cpp +++ b/src/lib/modes/aead/eax/eax.cpp @@ -5,15 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/eax.h> #include <botan/cmac.h> #include <botan/ctr.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(EAX_Encryption, EAX_Decryption, 0); + namespace { /* diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index 0acaa57e9..e4a2ad85c 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -6,9 +6,8 @@ */ #include <botan/gcm.h> +#include <botan/internal/mode_utils.h> #include <botan/ctr.h> -#include <botan/internal/xor_buf.h> -#include <botan/loadstor.h> #if defined(BOTAN_HAS_GCM_CLMUL) #include <botan/internal/clmul.h> @@ -17,6 +16,8 @@ namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(GCM_Encryption, GCM_Decryption, 16); + void GHASH::gcm_multiply(secure_vector<byte>& x) const { #if defined(BOTAN_HAS_GCM_CLMUL) diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp index 2ba30b2f9..2ba6d3ee6 100644 --- a/src/lib/modes/aead/ocb/ocb.cpp +++ b/src/lib/modes/aead/ocb/ocb.cpp @@ -5,14 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ocb.h> #include <botan/cmac.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/bit_ops.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(OCB_Encryption, OCB_Decryption, 16); + // Has to be in Botan namespace so unique_ptr can reference it class L_computer { diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp index b183bd6a0..c1416e209 100644 --- a/src/lib/modes/aead/siv/siv.cpp +++ b/src/lib/modes/aead/siv/siv.cpp @@ -5,15 +5,16 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/siv.h> #include <botan/cmac.h> #include <botan/ctr.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> -#include <algorithm> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE(SIV_Encryption, SIV_Decryption); + SIV_Mode::SIV_Mode(BlockCipher* cipher) : m_name(cipher->name() + "/SIV"), m_ctr(new CTR_BE(cipher->clone())), @@ -44,7 +45,7 @@ size_t SIV_Mode::update_granularity() const /* This value does not particularly matter as regardless SIV_Mode::update buffers all input, so in theory this could be 1. However as for instance - Transformation_Filter creates update_granularity() byte buffers, use a + Transform_Filter creates update_granularity() byte buffers, use a somewhat large size to avoid bouncing on a tiny buffer. */ return 128; diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp index e89635a5d..e54553d16 100644 --- a/src/lib/modes/cbc/cbc.cpp +++ b/src/lib/modes/cbc/cbc.cpp @@ -5,13 +5,34 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/cbc.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> +#include <botan/mode_pad.h> namespace Botan { +template<typename CBC_T, typename CTS_T> +Transform* make_cbc_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0)); + + if(bc) + { + const std::string padding = spec.arg(1, "PKCS7"); + + if(padding == "CTS") + return new CTS_T(bc->clone()); + else + return new CBC_T(bc->clone(), get_bc_pad(padding)); + } + + return nullptr; + } + +BOTAN_REGISTER_TRANSFORM(CBC_Encryption, (make_cbc_mode<CBC_Encryption,CTS_Encryption>)); +BOTAN_REGISTER_TRANSFORM(CBC_Decryption, (make_cbc_mode<CBC_Decryption,CTS_Decryption>)); + CBC_Mode::CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : m_cipher(cipher), m_padding(padding), diff --git a/src/lib/modes/cfb/cfb.cpp b/src/lib/modes/cfb/cfb.cpp index 5c33ee3cb..c1fd98dfb 100644 --- a/src/lib/modes/cfb/cfb.cpp +++ b/src/lib/modes/cfb/cfb.cpp @@ -5,12 +5,14 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/cfb.h> #include <botan/parsing.h> -#include <botan/internal/xor_buf.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(CFB_Encryption, CFB_Decryption, 0); + CFB_Mode::CFB_Mode(BlockCipher* cipher, size_t feedback_bits) : m_cipher(cipher), m_feedback_bytes(feedback_bits ? feedback_bits / 8 : cipher->block_size()) diff --git a/src/lib/modes/cipher_mode.cpp b/src/lib/modes/cipher_mode.cpp new file mode 100644 index 000000000..ded7b4c81 --- /dev/null +++ b/src/lib/modes/cipher_mode.cpp @@ -0,0 +1,59 @@ +/* +* Cipher Modes +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/cipher_mode.h> +#include <sstream> + +namespace Botan { + +Cipher_Mode* get_cipher_mode(const std::string& algo_spec, Cipher_Dir direction) + { + const char* dir_string = (direction == ENCRYPTION) ? "_Encryption" : "_Decryption"; + + const std::string provider = ""; + + std::unique_ptr<Transform> t; + + t.reset(get_transform(algo_spec, provider, dir_string)); + + if(Cipher_Mode* cipher = dynamic_cast<Cipher_Mode*>(t.get())) + { + t.release(); + return cipher; + } + + const std::vector<std::string> algo_parts = split_on(algo_spec, '/'); + if(algo_parts.size() < 2) + return nullptr; + + const std::string cipher_name = algo_parts[0]; + const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); + + if(mode_info.empty()) + return nullptr; + + std::ostringstream t_name; + + t_name << mode_info[0] << dir_string << '(' << cipher_name; + for(size_t i = 1; i < mode_info.size(); ++i) + t_name << ',' << mode_info[i]; + for(size_t i = 2; i < algo_parts.size(); ++i) + t_name << ',' << algo_parts[i]; + t_name << ')'; + + t.reset(get_transform(t_name.str(), provider)); + + if(Cipher_Mode* cipher = dynamic_cast<Cipher_Mode*>(t.get())) + { + t.release(); + return cipher; + } + + return nullptr; + } + +} diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h index 2f75fad1c..691852214 100644 --- a/src/lib/modes/cipher_mode.h +++ b/src/lib/modes/cipher_mode.h @@ -25,6 +25,8 @@ class BOTAN_DLL Cipher_Mode : public Keyed_Transform virtual bool authenticated() const { return false; } }; +BOTAN_DLL Cipher_Mode* get_cipher_mode(const std::string& algo_spec, Cipher_Dir direction); + } #endif diff --git a/src/lib/modes/ecb/ecb.cpp b/src/lib/modes/ecb/ecb.cpp index 53f54da99..1db272d12 100644 --- a/src/lib/modes/ecb/ecb.cpp +++ b/src/lib/modes/ecb/ecb.cpp @@ -5,13 +5,25 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/ecb.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> namespace Botan { +template<typename T> +Transform* make_ecb_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0)); + BlockCipherModePaddingMethod* pad = get_bc_pad(spec.arg(1, "NoPadding")); + if(bc && pad) + return new T(bc->clone(), pad); + return nullptr; + } + +BOTAN_REGISTER_TRANSFORM(ECB_Encryption, make_ecb_mode<ECB_Encryption>); +BOTAN_REGISTER_TRANSFORM(ECB_Decryption, make_ecb_mode<ECB_Decryption>); + ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : m_cipher(cipher), m_padding(padding) diff --git a/src/lib/modes/info.txt b/src/lib/modes/info.txt index 0dcb0cd59..b3d6d3b5f 100644 --- a/src/lib/modes/info.txt +++ b/src/lib/modes/info.txt @@ -2,3 +2,11 @@ <requires> block </requires> + +<header:public> +cipher_mode.h +</header:public> + +<header:internal> +mode_utils.h +</header:internal> diff --git a/src/lib/modes/mode_pad/mode_pad.cpp b/src/lib/modes/mode_pad/mode_pad.cpp index 946cd92c7..ecf241821 100644 --- a/src/lib/modes/mode_pad/mode_pad.cpp +++ b/src/lib/modes/mode_pad/mode_pad.cpp @@ -10,6 +10,26 @@ namespace Botan { +/** +* Get a block cipher padding method by name +*/ +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) + { + if(algo_spec == "NoPadding") + return new Null_Padding; + + if(algo_spec == "PKCS7") + return new PKCS7_Padding; + + if(algo_spec == "OneAndZeros") + return new OneAndZeros_Padding; + + if(algo_spec == "X9.23") + return new ANSI_X923_Padding; + + return nullptr; + } + /* * Pad with PKCS #7 Method */ diff --git a/src/lib/modes/mode_pad/mode_pad.h b/src/lib/modes/mode_pad/mode_pad.h index c60e25849..c4d5baf2e 100644 --- a/src/lib/modes/mode_pad/mode_pad.h +++ b/src/lib/modes/mode_pad/mode_pad.h @@ -119,6 +119,8 @@ class BOTAN_DLL Null_Padding : public BlockCipherModePaddingMethod std::string name() const { return "NoPadding"; } }; +BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec); + } #endif diff --git a/src/lib/modes/mode_utils.h b/src/lib/modes/mode_utils.h new file mode 100644 index 000000000..0333403a3 --- /dev/null +++ b/src/lib/modes/mode_utils.h @@ -0,0 +1,76 @@ +/* +* Helper include for mode implementations +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_MODE_UTILS_H__ +#define BOTAN_MODE_UTILS_H__ + +#include <botan/cipher_mode.h> +#include <botan/algo_registry.h> +#include <botan/block_cipher.h> +#include <botan/libstate.h> +#include <botan/loadstor.h> +#include <botan/internal/xor_buf.h> +#include <botan/internal/rounding.h> +#include <botan/internal/bit_ops.h> +#include <algorithm> + +namespace Botan { + +template<typename T> +T* make_block_cipher_mode(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + return new T(bc->clone()); + return nullptr; + } + +template<typename T, size_t LEN1> +T* make_block_cipher_mode_len(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + { + const size_t len1 = spec.arg_as_integer(1, LEN1); + return new T(bc->clone(), len1); + } + + return nullptr; + } + +template<typename T, size_t LEN1, size_t LEN2> +T* make_block_cipher_mode_len2(const Transform::Spec& spec) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + if(const BlockCipher* bc = af.prototype_block_cipher(spec.arg(0))) + { + const size_t len1 = spec.arg_as_integer(1, LEN1); + const size_t len2 = spec.arg_as_integer(2, LEN2); + return new T(bc->clone(), len1, len2); + } + + return nullptr; + } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE(E, D) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode<E>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode<D>); } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(E, D, LEN) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode_len<E, LEN>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode_len<D, LEN>); } + +#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(E, D, LEN1, LEN2) \ + namespace { Algo_Registry<Transform>::Add g_ ## E ## _reg(#E, make_block_cipher_mode_len2<E, LEN1, LEN2>); \ + Algo_Registry<Transform>::Add g_ ## D ## _reg(#D, make_block_cipher_mode_len2<D, LEN1, LEN2>); } + +} + +#endif diff --git a/src/lib/modes/xts/xts.cpp b/src/lib/modes/xts/xts.cpp index cd3a0c653..a4095580c 100644 --- a/src/lib/modes/xts/xts.cpp +++ b/src/lib/modes/xts/xts.cpp @@ -5,13 +5,13 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/mode_utils.h> #include <botan/xts.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> namespace Botan { +BOTAN_REGISTER_BLOCK_CIPHER_MODE(XTS_Encryption, XTS_Decryption); + namespace { void poly_double_128(byte out[], const byte in[]) diff --git a/src/lib/selftest/info.txt b/src/lib/selftest/info.txt deleted file mode 100644 index 265cc0bac..000000000 --- a/src/lib/selftest/info.txt +++ /dev/null @@ -1,8 +0,0 @@ -define SELFTESTS 20131128 - -<requires> -algo_factory -filters -aead_filt -core_engine -</requires> diff --git a/src/lib/selftest/selftest.cpp b/src/lib/selftest/selftest.cpp deleted file mode 100644 index f7e9ce01c..000000000 --- a/src/lib/selftest/selftest.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* -* Startup Self Tests -* (C) 1999-2007,2013 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/selftest.h> -#include <botan/filters.h> -#include <botan/aead_filt.h> -#include <botan/hex.h> -#include <botan/internal/core_engine.h> -#include <botan/internal/stl_util.h> - -namespace Botan { - -namespace { - -/* -* Perform a Known Answer Test -*/ -std::string test_filter_kat(Filter* filter, - const std::string& input, - const std::string& expected) - { - try - { - Pipe pipe(new Hex_Decoder, filter, new Hex_Encoder); - pipe.process_msg(input); - - const std::string got = pipe.read_all_as_string(); - - const bool same = (got == expected); - - if(same) - return "passed"; - else - return (std::string("got ") + got + " expected " + expected); - } - catch(std::exception& e) - { - return std::string("exception ") + e.what(); - } - } - -} - -/* -* Run a set of KATs -*/ -std::map<std::string, std::string> -algorithm_kat_detailed(const SCAN_Name& algo_name, - const std::map<std::string, std::string>& vars, - Algorithm_Factory& af) - { - const std::string& algo = algo_name.algo_name_and_args(); - - std::vector<std::string> providers = af.providers_of(algo); - std::map<std::string, std::string> all_results; - - if(providers.empty()) // no providers, nothing to do - return all_results; - - const std::string input = search_map(vars, std::string("input")); - const std::string output = search_map(vars, std::string("output")); - - SymmetricKey key(search_map(vars, std::string("key"))); - InitializationVector iv(search_map(vars, std::string("iv"))); - - for(size_t i = 0; i != providers.size(); ++i) - { - const std::string provider = providers[i]; - - if(const HashFunction* proto = - af.prototype_hash_function(algo, provider)) - { - Filter* filt = new Hash_Filter(proto->clone()); - all_results[provider] = test_filter_kat(filt, input, output); - } - else if(const MessageAuthenticationCode* proto = - af.prototype_mac(algo, provider)) - { - Keyed_Filter* filt = new MAC_Filter(proto->clone(), key); - all_results[provider] = test_filter_kat(filt, input, output); - } - else if(const StreamCipher* proto = - af.prototype_stream_cipher(algo, provider)) - { - Keyed_Filter* filt = new StreamCipher_Filter(proto->clone()); - filt->set_key(key); - filt->set_iv(iv); - - all_results[provider] = test_filter_kat(filt, input, output); - } - else if(const BlockCipher* proto = - af.prototype_block_cipher(algo, provider)) - { - std::unique_ptr<Keyed_Filter> enc(get_cipher_mode(proto, ENCRYPTION, - algo_name.cipher_mode(), - algo_name.cipher_mode_pad())); - - std::unique_ptr<Keyed_Filter> dec(get_cipher_mode(proto, DECRYPTION, - algo_name.cipher_mode(), - algo_name.cipher_mode_pad())); - - if(!enc || !dec) - continue; - - enc->set_key(key); - - if(enc->valid_iv_length(iv.length())) - enc->set_iv(iv); - else if(!enc->valid_iv_length(0)) - throw Invalid_IV_Length(algo, iv.length()); - - dec->set_key(key); - - if(dec->valid_iv_length(iv.length())) - dec->set_iv(iv); - else if(!dec->valid_iv_length(0)) - throw Invalid_IV_Length(algo, iv.length()); - - const std::vector<byte> ad = hex_decode(search_map(vars, std::string("ad"))); - - if(!ad.empty()) - { - if(AEAD_Filter* enc_aead = dynamic_cast<AEAD_Filter*>(enc.get())) - { - enc_aead->set_associated_data(&ad[0], ad.size()); - - if(AEAD_Filter* dec_aead = dynamic_cast<AEAD_Filter*>(dec.get())) - dec_aead->set_associated_data(&ad[0], ad.size()); - } - } - - all_results[provider + " (encrypt)"] = test_filter_kat(enc.release(), input, output); - all_results[provider + " (decrypt)"] = test_filter_kat(dec.release(), output, input); - } - } - - return all_results; - } - -std::map<std::string, bool> -algorithm_kat(const SCAN_Name& algo_name, - const std::map<std::string, std::string>& vars, - Algorithm_Factory& af) - { - const auto result = algorithm_kat_detailed(algo_name, vars, af); - - std::map<std::string, bool> pass_or_fail; - - for(auto i : result) - pass_or_fail[i.first] = (i.second == "passed"); - - return pass_or_fail; - } - -namespace { - -void verify_results(const std::string& algo, - const std::map<std::string, std::string>& results) - { - for(auto i = results.begin(); i != results.end(); ++i) - { - if(i->second != "passed") - throw Self_Test_Failure(algo + " self-test failed (" + i->second + ")" + - " with provider " + i->first); - } - } - -void hash_test(Algorithm_Factory& af, - const std::string& name, - const std::string& in, - const std::string& out) - { - std::map<std::string, std::string> vars; - vars["input"] = in; - vars["output"] = out; - - verify_results(name, algorithm_kat_detailed(name, vars, af)); - } - -void mac_test(Algorithm_Factory& af, - const std::string& name, - const std::string& in, - const std::string& out, - const std::string& key) - { - std::map<std::string, std::string> vars; - vars["input"] = in; - vars["output"] = out; - vars["key"] = key; - - verify_results(name, algorithm_kat_detailed(name, vars, af)); - } - -/* -* Perform a KAT for a cipher -*/ -void cipher_kat(Algorithm_Factory& af, - const std::string& algo, - const std::string& key_str, - const std::string& iv_str, - const std::string& in, - const std::string& ecb_out, - const std::string& cbc_out, - const std::string& cfb_out, - const std::string& ofb_out, - const std::string& ctr_out) - { - SymmetricKey key(key_str); - InitializationVector iv(iv_str); - - std::map<std::string, std::string> vars; - vars["key"] = key_str; - vars["iv"] = iv_str; - vars["input"] = in; - - std::map<std::string, bool> results; - - vars["output"] = ecb_out; - verify_results(algo + "/ECB", algorithm_kat_detailed(algo + "/ECB", vars, af)); - - vars["output"] = cbc_out; - verify_results(algo + "/CBC", - algorithm_kat_detailed(algo + "/CBC/NoPadding", vars, af)); - - vars["output"] = cfb_out; - verify_results(algo + "/CFB", algorithm_kat_detailed(algo + "/CFB", vars, af)); - - vars["output"] = ofb_out; - verify_results(algo + "/OFB", algorithm_kat_detailed(algo + "/OFB", vars, af)); - - vars["output"] = ctr_out; - verify_results(algo + "/CTR", algorithm_kat_detailed(algo + "/CTR-BE", vars, af)); - } - -} - -/* -* Perform Self Tests -*/ -bool passes_self_tests(Algorithm_Factory& af) - { - try - { - confirm_startup_self_tests(af); - } - catch(Self_Test_Failure) - { - return false; - } - - return true; - } - -/* -* Perform Self Tests -*/ -void confirm_startup_self_tests(Algorithm_Factory& af) - { - cipher_kat(af, "AES-128", - "2B7E151628AED2A6ABF7158809CF4F3C", - "000102030405060708090A0B0C0D0E0F", - "6BC1BEE22E409F96E93D7E117393172A" - "AE2D8A571E03AC9C9EB76FAC45AF8E51", - "3AD77BB40D7A3660A89ECAF32466EF97" - "F5D3D58503B9699DE785895A96FDBAAF", - "7649ABAC8119B246CEE98E9B12E9197D" - "5086CB9B507219EE95DB113A917678B2", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "C8A64537A0B3A93FCDE3CDAD9F1CE58B", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "7789508D16918F03F53C52DAC54ED825", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "010C041999E03F36448624483E582D0E"); - - hash_test(af, "SHA-1", - "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); - - hash_test(af, "SHA-1", - "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D"); - - hash_test(af, "SHA-1", - "6162636462636465636465666465666765666768666768696768696A" - "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", - "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); - - mac_test(af, "HMAC(SHA-1)", - "4869205468657265", - "B617318655057264E28BC0B6FB378C8EF146BE00", - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); - - hash_test(af, "SHA-256", - "", - "E3B0C44298FC1C149AFBF4C8996FB924" - "27AE41E4649B934CA495991B7852B855"); - - hash_test(af, "SHA-256", - "616263", - "BA7816BF8F01CFEA414140DE5DAE2223" - "B00361A396177A9CB410FF61F20015AD"); - - hash_test(af, "SHA-256", - "6162636462636465636465666465666765666768666768696768696A" - "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", - "248D6A61D20638B8E5C026930C3E6039" - "A33CE45964FF2167F6ECEDD419DB06C1"); - - mac_test(af, "HMAC(SHA-256)", - "4869205468657265", - "198A607EB44BFBC69903A0F1CF2BBDC5" - "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); - } - -} diff --git a/src/lib/selftest/selftest.h b/src/lib/selftest/selftest.h deleted file mode 100644 index 6ed552dc3..000000000 --- a/src/lib/selftest/selftest.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Startup Self Test -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_SELF_TESTS_H__ -#define BOTAN_SELF_TESTS_H__ - -#include <botan/algo_factory.h> -#include <botan/scan_name.h> -#include <map> -#include <string> - -namespace Botan { - -/** -* Run a set of self tests on some basic algorithms like AES and SHA-1 -* @param af an algorithm factory -* @throws Self_Test_Error if a failure occured -*/ -BOTAN_DLL void confirm_startup_self_tests(Algorithm_Factory& af); - -/** -* Run a set of self tests on some basic algorithms like AES and SHA-1 -* @param af an algorithm factory -* @returns false if a failure occured, otherwise true -*/ -BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af); - -/** -* Run a set of algorithm KATs (known answer tests) -* @param algo_name the algorithm we are testing -* @param vars a set of input variables for this test, all - hex encoded. Keys used: "input", "output", "key", and "iv" -* @param af an algorithm factory -* @returns map from provider name to test result for that provider -*/ -BOTAN_DLL std::map<std::string, bool> -algorithm_kat(const SCAN_Name& algo_name, - const std::map<std::string, std::string>& vars, - Algorithm_Factory& af); - -/** -* Run a set of algorithm KATs (known answer tests) -* @param algo_name the algorithm we are testing -* @param vars a set of input variables for this test, all - hex encoded. Keys used: "input", "output", "key", and "iv" -* @param af an algorithm factory -* @returns map from provider name to test result for that provider -*/ -BOTAN_DLL std::map<std::string, std::string> -algorithm_kat_detailed(const SCAN_Name& algo_name, - const std::map<std::string, std::string>& vars, - Algorithm_Factory& af); - -} - -#endif diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 7bbf7cd7e..f50cf1f3e 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -17,7 +17,7 @@ namespace TLS { std::vector<std::string> Policy::allowed_ciphers() const { - return std::vector<std::string>({ + return { //"AES-256/OCB(12)", //"AES-128/OCB(12)", "ChaCha20Poly1305", @@ -25,8 +25,8 @@ std::vector<std::string> Policy::allowed_ciphers() const "AES-128/GCM", "AES-256/CCM", "AES-128/CCM", - "AES-256/CCM-8", - "AES-128/CCM-8", + "AES-256/CCM(8)", + "AES-128/CCM(8)", //"Camellia-256/GCM", //"Camellia-128/GCM", "AES-256", @@ -36,35 +36,35 @@ std::vector<std::string> Policy::allowed_ciphers() const //"SEED" //"3DES", //"RC4", - }); + }; } std::vector<std::string> Policy::allowed_signature_hashes() const { - return std::vector<std::string>({ + return { "SHA-512", "SHA-384", "SHA-256", "SHA-224", //"SHA-1", //"MD5", - }); + }; } std::vector<std::string> Policy::allowed_macs() const { - return std::vector<std::string>({ + return { "AEAD", "SHA-384", "SHA-256", "SHA-1", //"MD5", - }); + }; } std::vector<std::string> Policy::allowed_key_exchange_methods() const { - return std::vector<std::string>({ + return { "SRP_SHA", //"ECDHE_PSK", //"DHE_PSK", @@ -72,22 +72,22 @@ std::vector<std::string> Policy::allowed_key_exchange_methods() const "ECDH", "DH", "RSA", - }); + }; } std::vector<std::string> Policy::allowed_signature_methods() const { - return std::vector<std::string>({ + return { "ECDSA", "RSA", "DSA", //"" - }); + }; } std::vector<std::string> Policy::allowed_ecc_curves() const { - return std::vector<std::string>({ + return { "brainpool512r1", "secp521r1", "brainpool384r1", @@ -102,7 +102,7 @@ std::vector<std::string> Policy::allowed_ecc_curves() const //"secp160r2", //"secp160r1", //"secp160k1", - }); + }; } /* @@ -352,6 +352,34 @@ void Policy::print(std::ostream& o) const o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n'; } +std::vector<std::string> Strict_Policy::allowed_ciphers() const + { + return { "ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM" }; + } + +std::vector<std::string> Strict_Policy::allowed_signature_hashes() const + { + return { "SHA-512", "SHA-384"}; + } + +std::vector<std::string> Strict_Policy::allowed_macs() const + { + return { "AEAD" }; + } + +std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const + { + return { "ECDH" }; + } + +bool Strict_Policy::acceptable_protocol_version(Protocol_Version version) const + { + if(version.is_datagram_protocol()) + return (version >= Protocol_Version::DTLS_V12); + else + return (version >= Protocol_Version::TLS_V12); + } + } } diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index 247510326..581d04bcd 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -229,27 +229,15 @@ class BOTAN_DLL Datagram_Policy : public Policy class BOTAN_DLL Strict_Policy : public Policy { public: - std::vector<std::string> allowed_ciphers() const override - { - return { "ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM" }; - } + std::vector<std::string> allowed_ciphers() const override; - std::vector<std::string> allowed_signature_hashes() const override - { return { "SHA-512", "SHA-384"}; } + std::vector<std::string> allowed_signature_hashes() const override; - std::vector<std::string> allowed_macs() const override - { return { "AEAD" }; } + std::vector<std::string> allowed_macs() const override; - std::vector<std::string> allowed_key_exchange_methods() const override - { return { "ECDH" }; } + std::vector<std::string> allowed_key_exchange_methods() const override; - bool acceptable_protocol_version(Protocol_Version version) const override - { - if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - else - return (version >= Protocol_Version::TLS_V12); - } + bool acceptable_protocol_version(Protocol_Version version) const override; }; class BOTAN_DLL Text_Policy : public Policy diff --git a/src/lib/tls/tls_suite_info.cpp b/src/lib/tls/tls_suite_info.cpp index 60777672a..02d277173 100644 --- a/src/lib/tls/tls_suite_info.cpp +++ b/src/lib/tls/tls_suite_info.cpp @@ -3,7 +3,7 @@ * * This file was automatically generated from the IANA assignments * (tls-parameters.txt hash 4bc98b6f75ad5b63952b5f457fa7adbfef60f095) -* by ./src/scripts/tls_suite_info.py on 2015-01-21 +* by ./src/scripts/tls_suite_info.py on 2015-01-30 * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -124,7 +124,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC09E, "RSA", "DH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A2: // DHE_RSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A2, "RSA", "DH", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A2, "RSA", "DH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0x009E: // DHE_RSA_WITH_AES_128_GCM_SHA256 return Ciphersuite(0x009E, "RSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); @@ -142,7 +142,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC09F, "RSA", "DH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A3: // DHE_RSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A3, "RSA", "DH", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A3, "RSA", "DH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0x009F: // DHE_RSA_WITH_AES_256_GCM_SHA384 return Ciphersuite(0x009F, "RSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); @@ -232,7 +232,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC0AC, "ECDSA", "ECDH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0AE: // ECDHE_ECDSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0AE, "ECDSA", "ECDH", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0AE, "ECDSA", "ECDH", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC02B: // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 return Ciphersuite(0xC02B, "ECDSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); @@ -250,7 +250,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC0AD, "ECDSA", "ECDH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0AF: // ECDHE_ECDSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0AF, "ECDSA", "ECDH", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0AF, "ECDSA", "ECDH", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0xC02C: // ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 return Ciphersuite(0xC02C, "ECDSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); @@ -364,10 +364,10 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC016, "", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20); case 0xC0AA: // PSK_DHE_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0AB: // PSK_DHE_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA return Ciphersuite(0x008B, "", "PSK", "3DES", 24, 8, 0, "SHA-1", 20); @@ -382,7 +382,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC0A4, "", "PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A8: // PSK_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A8, "", "PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A8, "", "PSK", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0x00A8: // PSK_WITH_AES_128_GCM_SHA256 return Ciphersuite(0x00A8, "", "PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); @@ -400,7 +400,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC0A5, "", "PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A9: // PSK_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A9, "", "PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A9, "", "PSK", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0x00A9: // PSK_WITH_AES_256_GCM_SHA384 return Ciphersuite(0x00A9, "", "PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); @@ -436,7 +436,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC09C, "RSA", "RSA", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A0: // RSA_WITH_AES_128_CCM_8 - return Ciphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM(8)", 16, 4, 8, "AEAD", 0, "SHA-256"); case 0x009C: // RSA_WITH_AES_128_GCM_SHA256 return Ciphersuite(0x009C, "RSA", "RSA", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256"); @@ -451,7 +451,7 @@ Ciphersuite Ciphersuite::by_id(u16bit suite) return Ciphersuite(0xC09D, "RSA", "RSA", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0xC0A1: // RSA_WITH_AES_256_CCM_8 - return Ciphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256"); + return Ciphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM(8)", 32, 4, 8, "AEAD", 0, "SHA-256"); case 0x009D: // RSA_WITH_AES_256_GCM_SHA384 return Ciphersuite(0x009D, "RSA", "RSA", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"); diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp index 7b7b27f7c..9dd2297e4 100644 --- a/src/lib/utils/cpuid.cpp +++ b/src/lib/utils/cpuid.cpp @@ -73,9 +73,10 @@ namespace Botan { -u64bit CPUID::m_x86_processor_flags[2] = { 0, 0 }; -size_t CPUID::m_cache_line_size = 0; -bool CPUID::m_altivec_capable = false; +u64bit CPUID::g_x86_processor_flags[2] = { 0, 0 }; +size_t CPUID::g_cache_line_size = 0; +bool CPUID::g_altivec_capable = false; +bool CPUID::g_initialized = false; namespace { @@ -183,9 +184,12 @@ void CPUID::print(std::ostream& o) void CPUID::initialize() { + if(g_initialized) + return; + #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) if(altivec_check_sysctl() || altivec_check_pvr_emul()) - m_altivec_capable = true; + g_altivec_capable = true; #endif #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) @@ -205,22 +209,22 @@ void CPUID::initialize() X86_CPUID(1, cpuid); - m_x86_processor_flags[0] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3]; + g_x86_processor_flags[0] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3]; if(is_intel) - m_cache_line_size = 8 * get_byte(2, cpuid[1]); + g_cache_line_size = 8 * get_byte(2, cpuid[1]); if(max_supported_sublevel >= 7) { clear_mem(cpuid, 4); X86_CPUID_SUBLEVEL(7, 0, cpuid); - m_x86_processor_flags[1] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[1]; + g_x86_processor_flags[1] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[1]; } if(is_amd) { X86_CPUID(0x80000005, cpuid); - m_cache_line_size = get_byte(3, cpuid[2]); + g_cache_line_size = get_byte(3, cpuid[2]); } #endif @@ -230,9 +234,11 @@ void CPUID::initialize() * If we don't have access to CPUID, we can still safely assume that * any x86-64 processor has SSE2 and RDTSC */ - if(m_x86_processor_flags[0] == 0) - m_x86_processor_flags[0] = (1 << CPUID_SSE2_BIT) | (1 << CPUID_RDTSC_BIT); + if(g_x86_processor_flags[0] == 0) + g_x86_processor_flags[0] = (1 << CPUID_SSE2_BIT) | (1 << CPUID_RDTSC_BIT); #endif + + g_initialized = true; } } diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid.h index cbbdcad6d..14901199c 100644 --- a/src/lib/utils/cpuid.h +++ b/src/lib/utils/cpuid.h @@ -27,7 +27,7 @@ class BOTAN_DLL CPUID /** * Return a best guess of the cache line size */ - static size_t cache_line_size() { return m_cache_line_size; } + static size_t cache_line_size() { return g_cache_line_size; } /** * Check if the processor supports RDTSC @@ -116,7 +116,7 @@ class BOTAN_DLL CPUID /** * Check if the processor supports AltiVec/VMX */ - static bool has_altivec() { return m_altivec_capable; } + static bool has_altivec() { return g_altivec_capable; } static void print(std::ostream& o); private: @@ -140,12 +140,15 @@ class BOTAN_DLL CPUID static bool x86_processor_flags_has(u64bit bit) { - return ((m_x86_processor_flags[bit/64] >> (bit % 64)) & 1); + if(!g_initialized) + initialize(); + return ((g_x86_processor_flags[bit/64] >> (bit % 64)) & 1); } - static u64bit m_x86_processor_flags[2]; - static size_t m_cache_line_size; - static bool m_altivec_capable; + static bool g_initialized; + static u64bit g_x86_processor_flags[2]; + static size_t g_cache_line_size; + static bool g_altivec_capable; }; } diff --git a/src/lib/utils/parsing.cpp b/src/lib/utils/parsing.cpp index ff8d5f0fb..36b168290 100644 --- a/src/lib/utils/parsing.cpp +++ b/src/lib/utils/parsing.cpp @@ -10,12 +10,20 @@ #include <botan/charset.h> #include <botan/get_byte.h> #include <set> +#include <stdexcept> namespace Botan { u32bit to_u32bit(const std::string& str) { - return std::stoul(str, nullptr); + try + { + return std::stoul(str, nullptr); + } + catch(std::exception&) + { + throw std::runtime_error("Could not read '" + str + "' as decimal string"); + } } /* |