diff options
Diffstat (limited to 'src')
89 files changed, 835 insertions, 1310 deletions
diff --git a/src/cmd/compress.cpp b/src/cmd/compress.cpp index 8480801e9..646a4d587 100644 --- a/src/cmd/compress.cpp +++ b/src/cmd/compress.cpp @@ -11,7 +11,7 @@ namespace { -void do_compress(Transformation& comp, std::ifstream& in, std::ostream& out) +void do_compress(Transform& comp, std::ifstream& in, std::ostream& out) { secure_vector<byte> buf; @@ -53,7 +53,13 @@ int compress(int argc, char* argv[]) const size_t level = 9; const std::string suffix = argc == 3 ? argv[2] : "gz"; - std::unique_ptr<Transformation> compress(make_compressor(suffix, level)); + std::unique_ptr<Transform> compress(make_compressor(suffix, level)); + + if(!compress) + { + std::cout << suffix << " compression not supported\n"; + return 1; + } const std::string out_file = in_file + "." + suffix; std::ofstream out(out_file.c_str()); @@ -91,7 +97,13 @@ int uncompress(int argc, char* argv[]) std::ofstream out(out_file.c_str()); - std::unique_ptr<Transformation> decompress(make_decompressor(suffix)); + std::unique_ptr<Transform> decompress(make_decompressor(suffix)); + + if(!decompress) + { + std::cout << suffix << " decompression not supported\n"; + return 1; + } do_compress(*decompress, in, out); diff --git a/src/cmd/speed.cpp b/src/cmd/speed.cpp index 8f19063be..4558c4250 100644 --- a/src/cmd/speed.cpp +++ b/src/cmd/speed.cpp @@ -121,7 +121,7 @@ void report_results(const std::string& algo, std::cout << std::endl; } -void time_transform(std::unique_ptr<Transformation> tf, +void time_transform(std::unique_ptr<Transform> tf, RandomNumberGenerator& rng) { if(!tf) @@ -162,7 +162,7 @@ void time_transform(std::unique_ptr<Transformation> tf, void time_transform(const std::string& algo, RandomNumberGenerator& rng) { - std::unique_ptr<Transformation> tf; + std::unique_ptr<Transform> tf; tf.reset(get_aead(algo, ENCRYPTION)); if(Keyed_Transform* keyed = dynamic_cast<Keyed_Transform*>(tf.get())) 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"); + } } /* diff --git a/src/scripts/tls_suite_info.py b/src/scripts/tls_suite_info.py index d569352ef..613332b14 100755 --- a/src/scripts/tls_suite_info.py +++ b/src/scripts/tls_suite_info.py @@ -49,7 +49,7 @@ def to_ciphersuite_info(code, name): cipher += ['CCM'] mac_algo = 'SHA256' elif mac_algo == 'CCM_8': - cipher += ['CCM-8'] + cipher += ['CCM(8)'] mac_algo = 'SHA256' cipher_info = { @@ -123,7 +123,7 @@ def to_ciphersuite_info(code, name): if cipher_algo not in stream_ciphers: mode = cipher[-1] - if mode not in ['CBC', 'GCM', 'CCM-8', 'CCM', 'OCB']: + if mode not in ['CBC', 'GCM', 'CCM(8)', 'CCM', 'OCB']: print "#warning Unknown mode %s" % (' '.join(cipher)) ivlen = 8 if cipher_algo == '3DES' else 16 diff --git a/src/tests/test_transform.cpp b/src/tests/test_transform.cpp index 41d992944..a4a26b0a7 100644 --- a/src/tests/test_transform.cpp +++ b/src/tests/test_transform.cpp @@ -15,24 +15,20 @@ using namespace Botan; namespace { -Transformation* get_transform(const std::string& algo) - { - throw std::runtime_error("Unknown transform " + algo); - } - secure_vector<byte> transform_test(const std::string& algo, const secure_vector<byte>& nonce, - const secure_vector<byte>& /*key*/, + const secure_vector<byte>& key, const secure_vector<byte>& in) { - std::unique_ptr<Transformation> transform(get_transform(algo)); + std::unique_ptr<Transform> t(get_transform(algo)); - //transform->set_key(key); - transform->start(nonce); + if(Keyed_Transform* keyed = dynamic_cast<Keyed_Transform*>(t.get())) + keyed->set_key(key); secure_vector<byte> out = in; - transform->update(out, 0); + t->start(nonce); + t->finish(out); return out; } |