diff options
Diffstat (limited to 'src')
95 files changed, 1485 insertions, 1673 deletions
diff --git a/src/lib/base/algo_registry.h b/src/lib/base/algo_registry.h deleted file mode 100644 index bca3715b6..000000000 --- a/src/lib/base/algo_registry.h +++ /dev/null @@ -1,299 +0,0 @@ -/* -* (C) 2014,2015 Jack Lloyd -* (C) 2015 Matej Kenda -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_ALGO_REGISTRY_H__ -#define BOTAN_ALGO_REGISTRY_H__ - -#include <botan/build.h> -#include <botan/types.h> -#include <botan/exceptn.h> -#include <botan/scan_name.h> -#include <functional> -#include <botan/mutex.h> -#include <vector> -#include <map> -#include <string> -#include <unordered_map> - -#if defined(_MSC_VER) && (_MSC_VER <= 1800) - - #define BOTAN_WORKAROUND_GH_321 - #define NOMINMAX 1 - #define WIN32_LEAN_AND_MEAN 1 - #include <windows.h> - -#endif - -namespace Botan { - -#if defined(BOTAN_WORKAROUND_GH_321) - -class WinCS_Mutex - { - public: - WinCS_Mutex() - { - ::InitializeCriticalSection(&m_cs); - } - - ~WinCS_Mutex() - { - ::DeleteCriticalSection(&m_cs); - } - - void lock() - { - ::EnterCriticalSection(&m_cs); - } - - void unlock() - { - ::LeaveCriticalSection(&m_cs); - } - - private: - CRITICAL_SECTION m_cs; - }; - -#endif - -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, byte pref) - { - lock_guard_type<af_mutex_type> lock(m_mutex); - if(!m_algo_info[name].add_provider(provider, fn, pref)) - throw Exception("Duplicated registration of " + name + "/" + provider); - } - - std::vector<std::string> providers_of(const Spec& spec) - { - lock_guard_type<af_mutex_type> lock(m_mutex); - auto i = m_algo_info.find(spec.algo_name()); - if(i != m_algo_info.end()) - return i->second.providers(); - return std::vector<std::string>(); - } - - void set_provider_preference(const Spec& spec, const std::string& provider, byte pref) - { - lock_guard_type<af_mutex_type> lock(m_mutex); - auto i = m_algo_info.find(spec.algo_name()); - if(i != m_algo_info.end()) - i->second.set_pref(provider, pref); - } - - T* make(const Spec& spec, const std::string& provider = "") - { - const std::vector<maker_fn> makers = get_makers(spec, provider); - - try - { - for(auto&& maker : makers) - { - if(T* t = maker(spec)) - return t; - } - } - catch(std::exception& e) - { - throw Lookup_Error("Creating '" + spec.as_string() + "' failed: " + e.what()); - } - - return nullptr; - } - - class Add - { - public: - Add(const std::string& basename, maker_fn fn, const std::string& provider, byte pref) - { - Algo_Registry<T>::global_registry().add(basename, provider, fn, pref); - } - - Add(bool cond, const std::string& basename, maker_fn fn, const std::string& provider, byte pref) - { - if(cond) - Algo_Registry<T>::global_registry().add(basename, provider, fn, pref); - } - }; - - private: - -#if defined(BOTAN_WORKAROUND_GH_321) - using af_mutex_type = WinCS_Mutex; -#else - using af_mutex_type = mutex_type; -#endif - - Algo_Registry() { } - - std::vector<maker_fn> get_makers(const Spec& spec, const std::string& provider) - { - lock_guard_type<af_mutex_type> lock(m_mutex); - return m_algo_info[spec.algo_name()].get_makers(provider); - } - - struct Algo_Info - { - public: - bool add_provider(const std::string& provider, maker_fn fn, byte pref) - { - if(m_maker_fns.count(provider) > 0) - return false; - - m_maker_fns[provider] = fn; - m_prefs.insert(std::make_pair(pref, provider)); - return true; - } - - std::vector<std::string> providers() const - { - std::vector<std::string> v; - for(auto&& k : m_prefs) - v.push_back(k.second); - return v; - } - - void set_pref(const std::string& provider, byte pref) - { - auto i = m_prefs.begin(); - while(i != m_prefs.end()) - { - if(i->second == provider) - i = m_prefs.erase(i); - else - ++i; - } - m_prefs.insert(std::make_pair(pref, provider)); - } - - std::vector<maker_fn> get_makers(const std::string& req_provider) - { - std::vector<maker_fn> r; - - if(!req_provider.empty()) - { - // find one explicit provider requested by user or fail - auto i = m_maker_fns.find(req_provider); - if(i != m_maker_fns.end()) - r.push_back(i->second); - } - else - { - for(auto&& pref : m_prefs) - r.push_back(m_maker_fns[pref.second]); - } - - return r; - } - private: - std::multimap<byte, std::string, std::greater<byte>> m_prefs; - std::unordered_map<std::string, maker_fn> m_maker_fns; - }; - - af_mutex_type m_mutex; - std::unordered_map<std::string, Algo_Info> m_algo_info; - }; - -template<typename T> T* -make_a(const typename T::Spec& spec, const std::string& provider = "") - { - return Algo_Registry<T>::global_registry().make(spec, provider); - } - -template<typename T> std::vector<std::string> providers_of(const typename T::Spec& spec) - { - return Algo_Registry<T>::global_registry().providers_of(spec); - } - -template<typename T> T* -make_new_T(const typename Algo_Registry<T>::Spec& spec) - { - if(spec.arg_count() == 0) - return new T; - return nullptr; - } - -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, size_t DEF1, size_t DEF2> T* -make_new_T_2len(const typename Algo_Registry<T>::Spec& spec) - { - return new T(spec.arg_as_integer(0, DEF1), spec.arg_as_integer(1, DEF2)); - } - -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)); - } - -template<typename T> T* -make_new_T_1str_req(const typename Algo_Registry<T>::Spec& spec) - { - return new T(spec.arg(0)); - } - -template<typename T, typename X> T* -make_new_T_1X(const typename Algo_Registry<T>::Spec& spec) - { - std::unique_ptr<X> x(Algo_Registry<X>::global_registry().make(Botan::SCAN_Name(spec.arg(0)))); - if(!x) - throw Exception(spec.arg(0)); - return new T(x.release()); - } - -#define BOTAN_REGISTER_TYPE(T, type, name, maker, provider, pref) \ - namespace { Algo_Registry<T>::Add g_ ## type ## _reg(name, maker, provider, pref); } \ - BOTAN_FORCE_SEMICOLON - -#define BOTAN_REGISTER_TYPE_COND(cond, T, type, name, maker, provider, pref) \ - namespace { Algo_Registry<T>::Add g_ ## type ## _reg(cond, name, maker, provider, pref); } \ - BOTAN_FORCE_SEMICOLON - -#define BOTAN_DEFAULT_ALGORITHM_PRIO 100 -#define BOTAN_SIMD_ALGORITHM_PRIO 110 - -#define BOTAN_REGISTER_NAMED_T(T, name, type, maker) \ - BOTAN_REGISTER_TYPE(T, type, name, maker, "base", BOTAN_DEFAULT_ALGORITHM_PRIO) - -#define BOTAN_REGISTER_T(T, type, maker) \ - BOTAN_REGISTER_TYPE(T, type, #type, maker, "base", BOTAN_DEFAULT_ALGORITHM_PRIO) - -#define BOTAN_REGISTER_T_NOARGS(T, type) \ - BOTAN_REGISTER_TYPE(T, type, #type, make_new_T<type>, "base", BOTAN_DEFAULT_ALGORITHM_PRIO) -#define BOTAN_REGISTER_T_1LEN(T, type, def) \ - BOTAN_REGISTER_TYPE(T, type, #type, (make_new_T_1len<type,def>), "base", BOTAN_DEFAULT_ALGORITHM_PRIO) - -#define BOTAN_REGISTER_NAMED_T_NOARGS(T, type, name, provider) \ - BOTAN_REGISTER_TYPE(T, type, name, make_new_T<type>, provider, BOTAN_DEFAULT_ALGORITHM_PRIO) -#define BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, T, type, name, provider, pref) \ - BOTAN_REGISTER_TYPE_COND(cond, T, type, name, make_new_T<type>, provider, pref) - -#define BOTAN_REGISTER_NAMED_T_2LEN(T, type, name, provider, len1, len2) \ - BOTAN_REGISTER_TYPE(T, type, name, (make_new_T_2len<type,len1,len2>), provider, BOTAN_DEFAULT_ALGORITHM_PRIO) - -} - -#endif diff --git a/src/lib/base/info.txt b/src/lib/base/info.txt index 7553007e5..001ed9e1b 100644 --- a/src/lib/base/info.txt +++ b/src/lib/base/info.txt @@ -10,10 +10,6 @@ sym_algo.h symkey.h </header:public> -<header:internal> -algo_registry.h -</header:internal> - <requires> block hash diff --git a/src/lib/base/scan_name.cpp b/src/lib/base/scan_name.cpp index 76d9b1a17..70c6e7f25 100644 --- a/src/lib/base/scan_name.cpp +++ b/src/lib/base/scan_name.cpp @@ -52,20 +52,8 @@ std::string make_arg( return output; } -std::pair<size_t, std::string> -deref_aliases(const std::pair<size_t, std::string>& in) - { - return std::make_pair(in.first, - SCAN_Name::deref_alias(in.second)); - } - } -SCAN_Name::SCAN_Name(std::string algo_spec, const std::string& extra) : SCAN_Name(algo_spec) - { - m_alg_name += extra; - } - SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec)) { } @@ -78,8 +66,6 @@ SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; - algo_spec = SCAN_Name::deref_alias(algo_spec); - for(size_t i = 0; i != algo_spec.size(); ++i) { char c = algo_spec[i]; @@ -100,7 +86,7 @@ SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg else { if(accum.second != "") - name.push_back(deref_aliases(accum)); + name.push_back(accum); accum = std::make_pair(level, ""); } } @@ -109,7 +95,7 @@ SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg } if(accum.second != "") - name.push_back(deref_aliases(accum)); + name.push_back(accum); if(level != 0) throw Decoding_Error(decoding_error + "Missing close paren"); @@ -133,23 +119,6 @@ SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg } } -std::string SCAN_Name::all_arguments() const - { - std::string out; - if(arg_count()) - { - out += "("; - for(size_t i = 0; i != arg_count(); ++i) - { - out += arg(i); - if(i != arg_count() - 1) - out += ","; - } - out += ")"; - } - return out; - } - std::string SCAN_Name::arg(size_t i) const { if(i >= arg_count()) @@ -172,47 +141,4 @@ size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const return to_u32bit(m_args[i]); } -mutex_type SCAN_Name::g_alias_map_mutex; -std::map<std::string, std::string> SCAN_Name::g_alias_map = { - { "3DES", "TripleDES" }, - { "ARC4", "RC4" }, - { "CAST5", "CAST-128" }, - { "DES-EDE", "TripleDES" }, - { "EME-OAEP", "OAEP" }, - { "EME-PKCS1-v1_5", "PKCS1v15" }, - { "EME1", "OAEP" }, - { "EMSA-PKCS1-v1_5", "EMSA_PKCS1" }, - { "EMSA-PSS", "PSSR" }, - { "EMSA2", "EMSA_X931" }, - { "EMSA3", "EMSA_PKCS1" }, - { "EMSA4", "PSSR" }, - { "GOST-34.11", "GOST-R-34.11-94" }, - { "MARK-4", "RC4(256)" }, - { "OMAC", "CMAC" }, - { "PSS-MGF1", "PSSR" }, - { "SHA-1", "SHA-160" }, - { "SHA1", "SHA-160" }, - { "X9.31", "EMSA2" } -}; - -void SCAN_Name::add_alias(const std::string& alias, const std::string& basename) - { - lock_guard_type<mutex_type> lock(g_alias_map_mutex); - - if(g_alias_map.find(alias) == g_alias_map.end()) - g_alias_map[alias] = basename; - } - -std::string SCAN_Name::deref_alias(const std::string& alias) - { - lock_guard_type<mutex_type> lock(g_alias_map_mutex); - - std::string name = alias; - - for(auto i = g_alias_map.find(name); i != g_alias_map.end(); i = g_alias_map.find(name)) - name = i->second; - - return name; - } - } diff --git a/src/lib/base/scan_name.h b/src/lib/base/scan_name.h index 75f7d1089..8356863ed 100644 --- a/src/lib/base/scan_name.h +++ b/src/lib/base/scan_name.h @@ -8,7 +8,7 @@ #ifndef BOTAN_SCAN_NAME_H__ #define BOTAN_SCAN_NAME_H__ -#include <botan/types.h> +#include <botan/exceptn.h> #include <string> #include <vector> #include <botan/mutex.h> @@ -36,13 +36,6 @@ class BOTAN_DLL SCAN_Name explicit SCAN_Name(std::string algo_spec); /** - * Create a SCAN_Name - * @param algo_spec A SCAN-format name - * @param extra An extra string appended to the algorithm name - */ - SCAN_Name(std::string algo_spec, const std::string& extra); - - /** * @return original input string */ const std::string& as_string() const { return m_orig_algo_spec; } @@ -53,16 +46,6 @@ class BOTAN_DLL SCAN_Name const std::string& algo_name() const { return m_alg_name; } /** - * @return algorithm name plus any arguments - */ - std::string algo_name_and_args() const { return algo_name() + all_arguments(); } - - /** - * @return all arguments - */ - std::string all_arguments() const; - - /** * @return number of arguments */ size_t arg_count() const { return m_args.size(); } @@ -107,15 +90,6 @@ class BOTAN_DLL SCAN_Name std::string cipher_mode_pad() const { return (m_mode_info.size() >= 2) ? m_mode_info[1] : ""; } - /* - * FIXME add doc - */ - static void add_alias(const std::string& alias, const std::string& basename); - - /* - * FIXME add doc - */ - static std::string deref_alias(const std::string& alias); private: static mutex_type g_alias_map_mutex; static std::map<std::string, std::string> g_alias_map; @@ -126,6 +100,23 @@ class BOTAN_DLL SCAN_Name std::vector<std::string> m_mode_info; }; +// This is unrelated but it is convenient to stash it here +template<typename T> +std::vector<std::string> probe_providers_of(const std::string& algo_spec, + const std::vector<std::string>& possible) + { + std::vector<std::string> providers; + for(auto&& prov : possible) + { + std::unique_ptr<T> o(T::create(algo_spec, prov)); + if(o) + { + providers.push_back(prov); // available + } + } + return providers; + } + } #endif diff --git a/src/lib/block/block_cipher.cpp b/src/lib/block/block_cipher.cpp index 2388057c6..750d01821 100644 --- a/src/lib/block/block_cipher.cpp +++ b/src/lib/block/block_cipher.cpp @@ -6,8 +6,7 @@ */ #include <botan/block_cipher.h> -#include <botan/cpuid.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_AES) #include <botan/aes.h> @@ -79,109 +78,220 @@ #include <botan/xtea.h> #endif -namespace Botan { +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> +#endif -BlockCipher::~BlockCipher() {} +namespace Botan { -std::unique_ptr<BlockCipher> BlockCipher::create(const std::string& algo_spec, - const std::string& provider) +std::unique_ptr<BlockCipher> +BlockCipher::create(const std::string& algo, + const std::string& provider) { - return std::unique_ptr<BlockCipher>(make_a<BlockCipher>(Botan::BlockCipher::Spec(algo_spec), provider)); - } +#if defined(BOTAN_HAS_OPENSSL) + if(provider.empty() || provider == "openssl") + { + if(auto bc = make_openssl_block_cipher(algo)) + return bc; -std::vector<std::string> BlockCipher::providers(const std::string& algo_spec) - { - return providers_of<BlockCipher>(BlockCipher::Spec(algo_spec)); - } + if(!provider.empty()) + return nullptr; + } +#endif -#define BOTAN_REGISTER_BLOCK_CIPHER(name, maker) BOTAN_REGISTER_T(BlockCipher, name, maker) -#define BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(name) BOTAN_REGISTER_T_NOARGS(BlockCipher, name) + // TODO: CommonCrypto + // TODO: CryptoAPI + // TODO: /dev/crypto -#define BOTAN_REGISTER_BLOCK_CIPHER_1LEN(name, def) BOTAN_REGISTER_T_1LEN(BlockCipher, name, def) + // Only base providers from here on out + if(provider.empty() == false && provider != "base") + return nullptr; -#define BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(type, name) \ - BOTAN_REGISTER_NAMED_T(BlockCipher, name, type, make_new_T<type>) -#define BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1LEN(type, name, def) \ - BOTAN_REGISTER_NAMED_T(BlockCipher, name, type, (make_new_T_1len<type,def>)) -#define BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1STR(type, name, def) \ - BOTAN_REGISTER_NAMED_T(BlockCipher, name, type, std::bind(make_new_T_1str<type>, std::placeholders::_1, def)) +#if defined(BOTAN_HAS_AES) + if(algo == "AES-128") + { + return std::unique_ptr<BlockCipher>(new AES_128); + } -#define BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(cond, type, name, provider, pref) \ - BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, BlockCipher, type, name, provider, pref) + if(algo == "AES-192") + { + return std::unique_ptr<BlockCipher>(new AES_192); + } -#if defined(BOTAN_HAS_AES) -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"); + if(algo == "AES-256") + { + return std::unique_ptr<BlockCipher>(new AES_256); + } +#endif + +#if defined(BOTAN_HAS_SERPENT) + if(algo == "Serpent") + { + return std::unique_ptr<BlockCipher>(new Serpent); + } +#endif + +#if defined(BOTAN_HAS_TWOFISH) + if(algo == "Twofish") + { + return std::unique_ptr<BlockCipher>(new Twofish); + } +#endif + +#if defined(BOTAN_HAS_THREEFISH_512) + if(algo == "Threefish-512") + { + return std::unique_ptr<BlockCipher>(new Threefish_512); + } #endif #if defined(BOTAN_HAS_BLOWFISH) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Blowfish); + if(algo == "Blowfish") + { + return std::unique_ptr<BlockCipher>(new Blowfish); + } #endif #if defined(BOTAN_HAS_CAMELLIA) -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"); -#endif + if(algo == "Camellia-128") + { + return std::unique_ptr<BlockCipher>(new Camellia_128); + } -#if defined(BOTAN_HAS_CAST) -BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(CAST_128, "CAST-128"); -BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(CAST_256, "CAST-256"); + if(algo == "Camellia-192") + { + return std::unique_ptr<BlockCipher>(new Camellia_192); + } + + if(algo == "Camellia-256") + { + return std::unique_ptr<BlockCipher>(new Camellia_256); + } #endif #if defined(BOTAN_HAS_DES) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(DES); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(TripleDES); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(DESX); + if(algo == "DES") + { + return std::unique_ptr<BlockCipher>(new DES); + } + + if(algo == "DESX") + { + return std::unique_ptr<BlockCipher>(new DESX); + } + + if(algo == "TripleDES" || algo == "3DES" || algo == "DES-EDE") + { + return std::unique_ptr<BlockCipher>(new TripleDES); + } #endif -#if defined(BOTAN_HAS_GOST_28147_89) -BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1STR(GOST_28147_89, "GOST-28147-89", "R3411_94_TestParam"); +#if defined(BOTAN_HAS_NOEKEON) + if(algo == "Noekeon") + { + return std::unique_ptr<BlockCipher>(new Noekeon); + } +#endif + +#if defined(BOTAN_HAS_CAST) + if(algo == "CAST-128" || algo == "CAST5") + { + return std::unique_ptr<BlockCipher>(new CAST_128); + } + + if(algo == "CAST-256") + { + return std::unique_ptr<BlockCipher>(new CAST_256); + } #endif #if defined(BOTAN_HAS_IDEA) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(IDEA); + if(algo == "IDEA") + { + return std::unique_ptr<BlockCipher>(new IDEA); + } #endif #if defined(BOTAN_HAS_KASUMI) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(KASUMI); + if(algo == "KASUMI") + { + return std::unique_ptr<BlockCipher>(new KASUMI); + } #endif #if defined(BOTAN_HAS_MISTY1) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MISTY1); -#endif - -#if defined(BOTAN_HAS_NOEKEON) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Noekeon); + if(algo == "MISTY1") + { + return std::unique_ptr<BlockCipher>(new MISTY1); + } #endif #if defined(BOTAN_HAS_SEED) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(SEED); + if(algo == "SEED") + { + return std::unique_ptr<BlockCipher>(new SEED); + } #endif -#if defined(BOTAN_HAS_SERPENT) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Serpent); -#endif - -#if defined(BOTAN_HAS_TWOFISH) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Twofish); +#if defined(BOTAN_HAS_XTEA) + if(algo == "XTEA") + { + return std::unique_ptr<BlockCipher>(new XTEA); + } #endif -#if defined(BOTAN_HAS_THREEFISH_512) -BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Threefish_512, "Threefish-512"); -#endif + const SCAN_Name req(algo); -#if defined(BOTAN_HAS_XTEA) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(XTEA); +#if defined(BOTAN_HAS_GOST_28147_89) + if(req.algo_name() == "GOST-28147-89") + { + return std::unique_ptr<BlockCipher>(new GOST_28147_89(req.arg(0, "R3411_94_TestParam"))); + } #endif #if defined(BOTAN_HAS_CASCADE) -BOTAN_REGISTER_NAMED_T(BlockCipher, "Cascade", Cascade_Cipher, Cascade_Cipher::make); + if(req.algo_name() == "Cascade" && req.arg_count() == 2) + { + std::unique_ptr<BlockCipher> c1(BlockCipher::create(req.arg(0))); + std::unique_ptr<BlockCipher> c2(BlockCipher::create(req.arg(1))); + + if(c1 && c2) + return std::unique_ptr<BlockCipher>(new Cascade_Cipher(c1.release(), c2.release())); + } #endif #if defined(BOTAN_HAS_LION) -BOTAN_REGISTER_NAMED_T(BlockCipher, "Lion", Lion, Lion::make); + if(req.algo_name() == "Lion" && req.arg_count_between(2, 3)) + { + std::unique_ptr<HashFunction> hash(HashFunction::create(req.arg(0))); + std::unique_ptr<StreamCipher> stream(StreamCipher::create(req.arg(1))); + + if(hash && stream) + { + const size_t block_size = req.arg_as_integer(2, 1024); + return std::unique_ptr<BlockCipher>(new Lion(hash.release(), stream.release(), block_size)); + } + } #endif + return nullptr; + } + +//static +std::unique_ptr<BlockCipher> +BlockCipher::create_or_throw(const std::string& algo, + const std::string& provider) + { + if(auto bc = BlockCipher::create(algo, provider)) + { + return bc; + } + throw Lookup_Error("Block cipher", algo, provider); + } + +std::vector<std::string> BlockCipher::providers(const std::string& algo) + { + return probe_providers_of<BlockCipher>(algo, { "base", "openssl" }); + } + } diff --git a/src/lib/block/block_cipher.h b/src/lib/block/block_cipher.h index 7c7084155..2062160bc 100644 --- a/src/lib/block/block_cipher.h +++ b/src/lib/block/block_cipher.h @@ -8,7 +8,6 @@ #ifndef BOTAN_BLOCK_CIPHER_H__ #define BOTAN_BLOCK_CIPHER_H__ -#include <botan/scan_name.h> #include <botan/sym_algo.h> #include <string> @@ -20,7 +19,6 @@ namespace Botan { class BOTAN_DLL BlockCipher : public SymmetricAlgorithm { public: - typedef SCAN_Name Spec; /** * Create an instance based on a name @@ -29,8 +27,18 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm * @param provider provider implementation to choose * @return a null pointer if the algo/provider combination cannot be found */ - static std::unique_ptr<BlockCipher> create(const std::string& algo_spec, - const std::string& provider = ""); + static std::unique_ptr<BlockCipher> + create(const std::string& algo_spec, + const std::string& provider = ""); + + /** + * Create an instance based on a name, or throw if the + * algo/provider combination cannot be found. If provider is + * empty then best available is chosen. + */ + static std::unique_ptr<BlockCipher> + create_or_throw(const std::string& algo_spec, + const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available @@ -165,7 +173,7 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm */ virtual BlockCipher* clone() const = 0; - virtual ~BlockCipher(); + virtual ~BlockCipher() {} }; /** diff --git a/src/lib/block/cascade/cascade.cpp b/src/lib/block/cascade/cascade.cpp index 100fb33ab..98e862de9 100644 --- a/src/lib/block/cascade/cascade.cpp +++ b/src/lib/block/cascade/cascade.cpp @@ -9,16 +9,6 @@ namespace Botan { -Cascade_Cipher* Cascade_Cipher::make(const BlockCipher::Spec& spec) - { - std::unique_ptr<BlockCipher> c1(BlockCipher::create(spec.arg(0))); - std::unique_ptr<BlockCipher> c2(BlockCipher::create(spec.arg(1))); - - if(c1 && c2) - return new Cascade_Cipher(c1.release(), c2.release()); - return nullptr; - } - void Cascade_Cipher::encrypt_n(const byte in[], byte out[], size_t blocks) const { diff --git a/src/lib/block/cascade/cascade.h b/src/lib/block/cascade/cascade.h index 21af5bea4..aa7bd0421 100644 --- a/src/lib/block/cascade/cascade.h +++ b/src/lib/block/cascade/cascade.h @@ -33,8 +33,6 @@ class BOTAN_DLL Cascade_Cipher final : public BlockCipher std::string name() const override; BlockCipher* clone() const override; - static Cascade_Cipher* make(const Spec& spec); - /** * Create a cascade of two block ciphers * @param cipher1 the first cipher diff --git a/src/lib/block/lion/lion.cpp b/src/lib/block/lion/lion.cpp index 7ae620504..56aa55c2f 100644 --- a/src/lib/block/lion/lion.cpp +++ b/src/lib/block/lion/lion.cpp @@ -10,22 +10,6 @@ namespace Botan { -Lion* Lion::make(const BlockCipher::Spec& spec) - { - if(spec.arg_count_between(2, 3)) - { - std::unique_ptr<HashFunction> hash(HashFunction::create(spec.arg(0))); - std::unique_ptr<StreamCipher> stream(StreamCipher::create(spec.arg(1))); - - if(hash && stream) - { - const size_t block_size = spec.arg_as_integer(2, 1024); - return new Lion(hash.release(), stream.release(), block_size); - } - } - return nullptr; - } - /* * Lion Encryption */ diff --git a/src/lib/block/lion/lion.h b/src/lib/block/lion/lion.h index f22f0f8a8..e6ecca64f 100644 --- a/src/lib/block/lion/lion.h +++ b/src/lib/block/lion/lion.h @@ -39,8 +39,6 @@ class BOTAN_DLL Lion final : public BlockCipher std::string name() const override; BlockCipher* clone() const override; - static Lion* make(const Spec&); - /** * @param hash the hash to use internally * @param cipher the stream cipher to use internally diff --git a/src/lib/compression/bzip2/bzip2.cpp b/src/lib/compression/bzip2/bzip2.cpp index 565eb09fc..1d1af7e29 100644 --- a/src/lib/compression/bzip2/bzip2.cpp +++ b/src/lib/compression/bzip2/bzip2.cpp @@ -8,6 +8,7 @@ */ #include <botan/bzip2.h> +#include <botan/exceptn.h> #include <botan/internal/compress_utils.h> #define BZ_NO_STDIO @@ -15,8 +16,6 @@ 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/compress_utils.cpp b/src/lib/compression/compress_utils.cpp new file mode 100644 index 000000000..2af629b9c --- /dev/null +++ b/src/lib/compression/compress_utils.cpp @@ -0,0 +1,189 @@ +/* +* Compression Utils +* (C) 2014,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> + +namespace Botan { + +void* Compression_Alloc_Info::do_malloc(size_t n, size_t size) + { + const size_t total_size = n * size; + + BOTAN_ASSERT_EQUAL(total_size / size, n, "Overflow check"); + + // TODO maximum length check here? + + void* ptr = std::malloc(total_size); + + /* + * Return null rather than throwing here as we are being called by a + * C library and it may not be possible for an exception to unwind + * the call stack from here. The compression library is expecting a + * function written in C and a null return on error, which it will + * send upwards to the compression wrappers. + */ + + if(ptr) + { + std::memset(ptr, 0, total_size); + m_current_allocs[ptr] = total_size; + } + + return ptr; + } + +void Compression_Alloc_Info::do_free(void* ptr) + { + if(ptr) + { + auto i = m_current_allocs.find(ptr); + + if(i == m_current_allocs.end()) + throw Exception("Compression_Alloc_Info::free got pointer not allocated by us"); + + zero_mem(ptr, i->second); + std::free(ptr); + m_current_allocs.erase(i); + } + } + +void Stream_Compression::clear() + { + m_stream.reset(); + } + +void Stream_Compression::start(size_t level) + { + m_stream.reset(make_stream(level)); + } + +void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) + { + BOTAN_ASSERT(m_stream, "Initialized"); + BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); + + if(m_buffer.size() < buf.size() + offset) + m_buffer.resize(buf.size() + offset); + + // If the output buffer has zero length, .data() might return nullptr. This would + // make some compression algorithms (notably those provided by zlib) fail. + // Any small positive value works fine, but we choose 32 as it is the smallest power + // of two that is large enough to hold all the headers and trailers of the common + // formats, preventing further resizings to make room for output data. + if(m_buffer.size() == 0) + m_buffer.resize(32); + + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); + + while(true) + { + m_stream->run(flags); + + if(m_stream->avail_out() == 0) + { + const size_t added = 8 + m_buffer.size(); + m_buffer.resize(m_buffer.size() + added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); + } + else if(m_stream->avail_in() == 0) + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + break; + } + } + + copy_mem(m_buffer.data(), buf.data(), offset); + buf.swap(m_buffer); + } + +void Stream_Compression::update(secure_vector<byte>& buf, size_t offset, bool flush) + { + BOTAN_ASSERT(m_stream, "Initialized"); + process(buf, offset, flush ? m_stream->flush_flag() : m_stream->run_flag()); + } + +void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset) + { + BOTAN_ASSERT(m_stream, "Initialized"); + process(buf, offset, m_stream->finish_flag()); + clear(); + } + +void Stream_Decompression::clear() + { + m_stream.reset(); + } + +void Stream_Decompression::start() + { + m_stream.reset(make_stream()); + } + +void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) + { + BOTAN_ASSERT(m_stream, "Initialized"); + BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); + + if(m_buffer.size() < buf.size() + offset) + m_buffer.resize(buf.size() + offset); + + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); + + while(true) + { + const bool stream_end = m_stream->run(flags); + + if(stream_end) + { + if(m_stream->avail_in() == 0) // all data consumed? + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + clear(); + break; + } + + // More data follows: try to process as a following stream + const size_t read = (buf.size() - offset) - m_stream->avail_in(); + start(); + m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read); + } + + if(m_stream->avail_out() == 0) + { + const size_t added = 8 + m_buffer.size(); + m_buffer.resize(m_buffer.size() + added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); + } + else if(m_stream->avail_in() == 0) + { + m_buffer.resize(m_buffer.size() - m_stream->avail_out()); + break; + } + } + + copy_mem(m_buffer.data(), buf.data(), offset); + buf.swap(m_buffer); + } + +void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset) + { + process(buf, offset, m_stream->run_flag()); + } + +void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset) + { + if(buf.size() != offset || m_stream.get()) + process(buf, offset, m_stream->finish_flag()); + + if(m_stream.get()) + throw Exception(name() + " finished but not at stream end"); + } + +} diff --git a/src/lib/compression/compress_utils.h b/src/lib/compression/compress_utils.h index a60ae3c22..9f6871a0b 100644 --- a/src/lib/compression/compress_utils.h +++ b/src/lib/compression/compress_utils.h @@ -9,7 +9,6 @@ #define BOTAN_COMPRESSION_UTILS_H__ #include <botan/compression.h> -#include <botan/internal/algo_registry.h> #include <memory> #include <unordered_map> @@ -85,10 +84,6 @@ class Zlib_Style_Stream : public Compression_Stream std::unique_ptr<Compression_Alloc_Info> m_allocs; }; -#define BOTAN_REGISTER_COMPRESSION(C, D) \ - BOTAN_REGISTER_T_NOARGS(Compression_Algorithm, C); \ - BOTAN_REGISTER_T_NOARGS(Decompression_Algorithm, D) - } #endif diff --git a/src/lib/compression/compression.cpp b/src/lib/compression/compression.cpp index f289aa79f..92004a071 100644 --- a/src/lib/compression/compression.cpp +++ b/src/lib/compression/compression.cpp @@ -1,233 +1,75 @@ /* -* Compression Transform -* (C) 2014 Jack Lloyd +* Compression Factory +* (C) 2014,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/compression.h> -#include <botan/internal/compress_utils.h> #include <botan/mem_ops.h> #include <cstdlib> -namespace Botan { - -void* Compression_Alloc_Info::do_malloc(size_t n, size_t size) - { - const size_t total_size = n * size; - - BOTAN_ASSERT_EQUAL(total_size / size, n, "Overflow check"); - - // TODO maximum length check here? - - void* ptr = std::malloc(total_size); - - /* - * Return null rather than throwing here as we are being called by a - * C library and it may not be possible for an exception to unwind - * the call stack from here. The compression library is expecting a - * function written in C and a null return on error, which it will - * send upwards to the compression wrappers. - */ - - if(ptr) - { - std::memset(ptr, 0, total_size); - m_current_allocs[ptr] = total_size; - } - - return ptr; - } - -void Compression_Alloc_Info::do_free(void* ptr) - { - if(ptr) - { - auto i = m_current_allocs.find(ptr); - - if(i == m_current_allocs.end()) - throw Exception("Compression_Alloc_Info::free got pointer not allocated by us"); - - zero_mem(ptr, i->second); - std::free(ptr); - m_current_allocs.erase(i); - } - } - -Compression_Algorithm* make_compressor(const std::string& type) - { - const std::map<std::string, std::string> trans{ - {"zlib", "Zlib"}, - {"deflate", "Deflate"}, - {"gzip", "Gzip"}, - {"gz", "Gzip"}, - {"bzip2", "Bzip2"}, - {"bz2", "Bzip2"}, - {"lzma", "LZMA"}, - {"xz", "LZMA"}}; - - auto i = trans.find(type); - - if(i == trans.end()) - return nullptr; - - const SCAN_Name t_name(i->second + "_Compression"); - return Algo_Registry<Compression_Algorithm>::global_registry().make(t_name); - } - -Decompression_Algorithm* make_decompressor(const std::string& type) - { - const std::map<std::string, std::string> trans{ - {"zlib", "Zlib"}, - {"deflate", "Deflate"}, - {"gzip", "Gzip"}, - {"gz", "Gzip"}, - {"bzip2", "Bzip2"}, - {"bz2", "Bzip2"}, - {"lzma", "LZMA"}, - {"xz", "LZMA"}}; - - auto i = trans.find(type); - - if(i == trans.end()) - return nullptr; - - const SCAN_Name t_name(i->second + "_Decompression"); - return Algo_Registry<Decompression_Algorithm>::global_registry().make(t_name); - } - -void Stream_Compression::clear() - { - m_stream.reset(); - } - -void Stream_Compression::start(size_t level) - { - m_stream.reset(make_stream(level)); - } - -void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) - { - BOTAN_ASSERT(m_stream, "Initialized"); - BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); - - if(m_buffer.size() < buf.size() + offset) - m_buffer.resize(buf.size() + offset); - - // If the output buffer has zero length, .data() might return nullptr. This would - // make some compression algorithms (notably those provided by zlib) fail. - // Any small positive value works fine, but we choose 32 as it is the smallest power - // of two that is large enough to hold all the headers and trailers of the common - // formats, preventing further resizings to make room for output data. - if(m_buffer.size() == 0) - m_buffer.resize(32); - - m_stream->next_in(buf.data() + offset, buf.size() - offset); - m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); - - while(true) - { - m_stream->run(flags); +#if defined(BOTAN_HAS_ZLIB) + #include <botan/zlib.h> +#endif - if(m_stream->avail_out() == 0) - { - const size_t added = 8 + m_buffer.size(); - m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); - } - else if(m_stream->avail_in() == 0) - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - break; - } - } +#if defined(BOTAN_HAS_BZIP2) + #include <botan/bzip2.h> +#endif - copy_mem(m_buffer.data(), buf.data(), offset); - buf.swap(m_buffer); - } - -void Stream_Compression::update(secure_vector<byte>& buf, size_t offset, bool flush) - { - BOTAN_ASSERT(m_stream, "Initialized"); - process(buf, offset, flush ? m_stream->flush_flag() : m_stream->run_flag()); - } +#if defined(BOTAN_HAS_LZMA) + #include <botan/lzma.h> +#endif -void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset) - { - BOTAN_ASSERT(m_stream, "Initialized"); - process(buf, offset, m_stream->finish_flag()); - clear(); - } - -void Stream_Decompression::clear() - { - m_stream.reset(); - } +namespace Botan { -void Stream_Decompression::start() +Compression_Algorithm* make_compressor(const std::string& name) { - m_stream.reset(make_stream()); +#if defined(BOTAN_HAS_ZLIB) + if(name == "Zlib" || name == "zlib") + return new Zlib_Compression; + if(name == "Gzip" || name == "gzip" || name == "gz") + return new Gzip_Compression; + if(name == "Deflate" || name == "deflate") + return new Deflate_Compression; +#endif + +#if defined(BOTAN_HAS_BZIP2) + if(name == "bzip2" || name == "bz2" || name == "Bzip2") + return new Bzip2_Compression; +#endif + +#if defined(BOTAN_HAS_LZMA) + if(name == "lzma" || name == "xz" || name == "LZMA") + return new LZMA_Compression; +#endif + + return nullptr; } -void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags) +Decompression_Algorithm* make_decompressor(const std::string& name) { - BOTAN_ASSERT(m_stream, "Initialized"); - BOTAN_ASSERT(buf.size() >= offset, "Offset is sane"); - - if(m_buffer.size() < buf.size() + offset) - m_buffer.resize(buf.size() + offset); - - m_stream->next_in(buf.data() + offset, buf.size() - offset); - m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); - - while(true) - { - const bool stream_end = m_stream->run(flags); - - if(stream_end) - { - if(m_stream->avail_in() == 0) // all data consumed? - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - clear(); - break; - } - - // More data follows: try to process as a following stream - const size_t read = (buf.size() - offset) - m_stream->avail_in(); - start(); - m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read); - } - - if(m_stream->avail_out() == 0) - { - const size_t added = 8 + m_buffer.size(); - m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); - } - else if(m_stream->avail_in() == 0) - { - m_buffer.resize(m_buffer.size() - m_stream->avail_out()); - break; - } - } - - copy_mem(m_buffer.data(), buf.data(), offset); - buf.swap(m_buffer); - } - -void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset) - { - process(buf, offset, m_stream->run_flag()); +#if defined(BOTAN_HAS_ZLIB) + if(name == "Zlib" || name == "zlib") + return new Zlib_Decompression; + if(name == "Gzip" || name == "gzip" || name == "gz") + return new Gzip_Decompression; + if(name == "Deflate" || name == "deflate") + return new Deflate_Decompression; +#endif + +#if defined(BOTAN_HAS_BZIP2) + if(name == "bzip2" || name == "bz2" || name == "Bzip2") + return new Bzip2_Decompression; +#endif + +#if defined(BOTAN_HAS_LZMA) + if(name == "lzma" || name == "xz" || name == "LZMA") + return new LZMA_Decompression; +#endif + + return nullptr; } -void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset) - { - if(buf.size() != offset || m_stream.get()) - process(buf, offset, m_stream->finish_flag()); - - if(m_stream.get()) - throw Exception(name() + " finished but not at stream end"); - } } diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h index f135f6d04..1c429195c 100644 --- a/src/lib/compression/compression.h +++ b/src/lib/compression/compression.h @@ -9,7 +9,7 @@ #define BOTAN_COMPRESSION_TRANSFORM_H__ #include <botan/secmem.h> -#include <botan/scan_name.h> +#include <string> namespace Botan { @@ -19,8 +19,6 @@ namespace Botan { class BOTAN_DLL Compression_Algorithm { public: - typedef SCAN_Name Spec; - /** * Begin compressing. Most compression algorithms offer a tunable * time/compression tradeoff parameter generally represented by @@ -67,8 +65,6 @@ class BOTAN_DLL Compression_Algorithm class BOTAN_DLL Decompression_Algorithm { public: - typedef SCAN_Name Spec; - /** * Begin decompressing. * Decompression does not support levels, as compression does. @@ -108,7 +104,7 @@ BOTAN_DLL Compression_Algorithm* make_compressor(const std::string& type); BOTAN_DLL Decompression_Algorithm* make_decompressor(const std::string& type); /** -* FIXME add doc +* Adapts a zlib style API */ class Compression_Stream { @@ -131,7 +127,7 @@ class Compression_Stream }; /** -* FIXME add doc +* Used to implement compression using Compression_Stream */ class Stream_Compression : public Compression_Algorithm { diff --git a/src/lib/compression/lzma/lzma.cpp b/src/lib/compression/lzma/lzma.cpp index 18701278d..3831ef68c 100644 --- a/src/lib/compression/lzma/lzma.cpp +++ b/src/lib/compression/lzma/lzma.cpp @@ -10,12 +10,11 @@ #include <botan/lzma.h> #include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> #include <lzma.h> 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 836925a68..27ae6fb20 100644 --- a/src/lib/compression/zlib/zlib.cpp +++ b/src/lib/compression/zlib/zlib.cpp @@ -9,15 +9,12 @@ #include <botan/zlib.h> #include <botan/internal/compress_utils.h> +#include <botan/exceptn.h> #include <ctime> #include <zlib.h> 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/filters/filters.h b/src/lib/filters/filters.h index 2b6e2b1cd..af2b6c70d 100644 --- a/src/lib/filters/filters.h +++ b/src/lib/filters/filters.h @@ -18,8 +18,6 @@ #include <botan/key_filt.h> #include <botan/data_snk.h> -#include <botan/scan_name.h> - #if defined(BOTAN_HAS_CODEC_FILTERS) #include <botan/b64_filt.h> #include <botan/hex_filt.h> diff --git a/src/lib/hash/blake2/blake2b.cpp b/src/lib/hash/blake2/blake2b.cpp index 10ccbf5c0..928f344d7 100644 --- a/src/lib/hash/blake2/blake2b.cpp +++ b/src/lib/hash/blake2/blake2b.cpp @@ -39,11 +39,6 @@ const u64bit blake2b_sigma[12][16] = { }; } -Blake2b* Blake2b::make(const Spec& spec) - { - return new Blake2b(spec.arg_as_integer(0, 512)); - } - Blake2b::Blake2b(size_t output_bits) : m_output_bits(output_bits), m_buffer(BLAKE2B_BLOCKBYTES), diff --git a/src/lib/hash/blake2/blake2b.h b/src/lib/hash/blake2/blake2b.h index 290db10f0..343f276b5 100644 --- a/src/lib/hash/blake2/blake2b.h +++ b/src/lib/hash/blake2/blake2b.h @@ -34,8 +34,6 @@ class BOTAN_DLL Blake2b final : public HashFunction size_t hash_block_size() const override { return BLAKE2B_BLOCKBYTES; } size_t output_length() const override { return m_output_bits / 8; } - static Blake2b* make(const Spec& spec); - HashFunction* clone() const override; std::string name() const override; void clear() override; diff --git a/src/lib/hash/comb4p/comb4p.cpp b/src/lib/hash/comb4p/comb4p.cpp index 015873473..4659ace77 100644 --- a/src/lib/hash/comb4p/comb4p.cpp +++ b/src/lib/hash/comb4p/comb4p.cpp @@ -33,19 +33,6 @@ void comb4p_round(secure_vector<byte>& out, } -Comb4P* Comb4P::make(const Spec& spec) - { - if(spec.arg_count() == 2) - { - std::unique_ptr<HashFunction> h1(HashFunction::create(spec.arg(0))); - std::unique_ptr<HashFunction> h2(HashFunction::create(spec.arg(1))); - - if(h1 && h2) - return new Comb4P(h1.release(), h2.release()); - } - return nullptr; - } - Comb4P::Comb4P(HashFunction* h1, HashFunction* h2) : m_hash1(h1), m_hash2(h2) { diff --git a/src/lib/hash/comb4p/comb4p.h b/src/lib/hash/comb4p/comb4p.h index c05953ea5..cb78914e7 100644 --- a/src/lib/hash/comb4p/comb4p.h +++ b/src/lib/hash/comb4p/comb4p.h @@ -32,8 +32,6 @@ class BOTAN_DLL Comb4P final : public HashFunction return m_hash1->output_length() + m_hash2->output_length(); } - static Comb4P* make(const Spec& spec); - HashFunction* clone() const override { return new Comb4P(m_hash1->clone(), m_hash2->clone()); diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp index 016f60df1..7a32ccede 100644 --- a/src/lib/hash/hash.cpp +++ b/src/lib/hash/hash.cpp @@ -6,8 +6,7 @@ */ #include <botan/hash.h> -#include <botan/cpuid.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_ADLER32) #include <botan/adler32.h> @@ -81,109 +80,225 @@ #include <botan/blake2b.h> #endif +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> +#endif + namespace Botan { std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec, const std::string& provider) { - return std::unique_ptr<HashFunction>(make_a<HashFunction>(Botan::HashFunction::Spec(algo_spec), provider)); - } +#if defined(BOTAN_HAS_OPENSSL) + if(provider.empty() || provider == "openssl") + { + if(auto hash = make_openssl_hash(algo_spec)) + return hash; -std::vector<std::string> HashFunction::providers(const std::string& algo_spec) - { - return providers_of<HashFunction>(HashFunction::Spec(algo_spec)); - } + if(!provider.empty()) + return nullptr; + } +#endif + + // TODO: CommonCrypto hashes -HashFunction::HashFunction() {} + if(provider.empty() == false && provider != "base") + return nullptr; // unknown provider -HashFunction::~HashFunction() {} +#if defined(BOTAN_HAS_SHA1) + if(algo_spec == "SHA-160" || + algo_spec == "SHA-1" || + algo_spec == "SHA1") + { + return std::unique_ptr<HashFunction>(new SHA_160); + } +#endif -#define BOTAN_REGISTER_HASH(name, maker) BOTAN_REGISTER_T(HashFunction, name, maker) -#define BOTAN_REGISTER_HASH_NOARGS(name) BOTAN_REGISTER_T_NOARGS(HashFunction, name) +#if defined(BOTAN_HAS_SHA2_32) + if(algo_spec == "SHA-224") + { + return std::unique_ptr<HashFunction>(new SHA_224); + } -#define BOTAN_REGISTER_HASH_1LEN(name, def) BOTAN_REGISTER_T_1LEN(HashFunction, name, def) + if(algo_spec == "SHA-256") + { + return std::unique_ptr<HashFunction>(new SHA_256); + } +#endif -#define BOTAN_REGISTER_HASH_NAMED_NOARGS(type, name) \ - BOTAN_REGISTER_NAMED_T(HashFunction, name, type, make_new_T<type>) -#define BOTAN_REGISTER_HASH_NAMED_1LEN(type, name, def) \ - BOTAN_REGISTER_NAMED_T(HashFunction, name, type, (make_new_T_1len<type,def>)) +#if defined(BOTAN_HAS_SHA2_64) + if(algo_spec == "SHA-384") + { + return std::unique_ptr<HashFunction>(new SHA_384); + } -#define BOTAN_REGISTER_HASH_NOARGS_IF(cond, type, name, provider, pref) \ - BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, HashFunction, type, name, provider, pref) + if(algo_spec == "SHA-512") + { + return std::unique_ptr<HashFunction>(new SHA_512); + } -#if defined(BOTAN_HAS_ADLER32) -BOTAN_REGISTER_HASH_NOARGS(Adler32); + if(algo_spec == "SHA-512-256") + { + return std::unique_ptr<HashFunction>(new SHA_512_256); + } #endif -#if defined(BOTAN_HAS_CRC24) -BOTAN_REGISTER_HASH_NOARGS(CRC24); +#if defined(BOTAN_HAS_RIPEMD_160) + if(algo_spec == "RIPEMD-160") + { + return std::unique_ptr<HashFunction>(new RIPEMD_160); + } #endif -#if defined(BOTAN_HAS_CRC32) -BOTAN_REGISTER_HASH_NOARGS(CRC32); +#if defined(BOTAN_HAS_WHIRLPOOL) + if(algo_spec == "Whirlpool") + { + return std::unique_ptr<HashFunction>(new Whirlpool); + } #endif -#if defined(BOTAN_HAS_COMB4P) -BOTAN_REGISTER_NAMED_T(HashFunction, "Comb4P", Comb4P, Comb4P::make); +#if defined(BOTAN_HAS_MD5) + if(algo_spec == "MD5") + { + return std::unique_ptr<HashFunction>(new MD5); + } #endif -#if defined(BOTAN_HAS_PARALLEL_HASH) -BOTAN_REGISTER_NAMED_T(HashFunction, "Parallel", Parallel, Parallel::make); +#if defined(BOTAN_HAS_MD4) + if(algo_spec == "MD4") + { + return std::unique_ptr<HashFunction>(new MD4); + } #endif #if defined(BOTAN_HAS_GOST_34_11) -BOTAN_REGISTER_HASH_NAMED_NOARGS(GOST_34_11, "GOST-R-34.11-94"); + if(algo_spec == "GOST-R-34.11-94" || algo_spec == "GOST-34.11") + { + return std::unique_ptr<HashFunction>(new GOST_34_11); + } #endif -#if defined(BOTAN_HAS_KECCAK) -BOTAN_REGISTER_HASH_NAMED_1LEN(Keccak_1600, "Keccak-1600", 512); +#if defined(BOTAN_HAS_ADLER32) + if(algo_spec == "Adler32") + { + return std::unique_ptr<HashFunction>(new Adler32); + } #endif -#if defined(BOTAN_HAS_SHA3) -BOTAN_REGISTER_HASH_NAMED_1LEN(SHA_3, "SHA-3", 512); +#if defined(BOTAN_HAS_CRC24) + if(algo_spec == "CRC24") + { + return std::unique_ptr<HashFunction>(new CRC24); + } #endif -#if defined(BOTAN_HAS_MD4) -BOTAN_REGISTER_HASH_NOARGS(MD4); +#if defined(BOTAN_HAS_CRC32) + if(algo_spec == "CRC32") + { + return std::unique_ptr<HashFunction>(new CRC32); + } #endif -#if defined(BOTAN_HAS_MD5) -BOTAN_REGISTER_HASH_NOARGS(MD5); -#endif + const SCAN_Name req(algo_spec); -#if defined(BOTAN_HAS_RIPEMD_160) -BOTAN_REGISTER_HASH_NAMED_NOARGS(RIPEMD_160, "RIPEMD-160"); +#if defined(BOTAN_HAS_TIGER) + if(req.algo_name() == "Tiger") + { + return std::unique_ptr<HashFunction>( + new Tiger(req.arg_as_integer(0, 24), + req.arg_as_integer(1, 3))); + } #endif -#if defined(BOTAN_HAS_SHA1) -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_160, "SHA-160"); +#if defined(BOTAN_HAS_SKEIN_512) + if(req.algo_name() == "Skein-512") + { + return std::unique_ptr<HashFunction>( + new Skein_512(req.arg_as_integer(0, 512), req.arg(1, ""))); + } #endif -#if defined(BOTAN_HAS_SHA2_32) -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_224, "SHA-224"); -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_256, "SHA-256"); +#if defined(BOTAN_HAS_BLAKE2B) + if(req.algo_name() == "Blake2b") + { + return std::unique_ptr<HashFunction>( + new Blake2b(req.arg_as_integer(0, 512))); + } #endif -#if defined(BOTAN_HAS_SHA2_64) -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_384, "SHA-384"); -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_512, "SHA-512"); -BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_512_256, "SHA-512-256"); +#if defined(BOTAN_HAS_KECCAK) + if(req.algo_name() == "Keccak-1600") + { + return std::unique_ptr<HashFunction>( + new Keccak_1600(req.arg_as_integer(0, 512))); + } #endif -#if defined(BOTAN_HAS_TIGER) -BOTAN_REGISTER_NAMED_T_2LEN(HashFunction, Tiger, "Tiger", "base", 24, 3); +#if defined(BOTAN_HAS_SHA3) + if(req.algo_name() == "SHA-3") + { + return std::unique_ptr<HashFunction>( + new SHA_3(req.arg_as_integer(0, 512))); + } #endif -#if defined(BOTAN_HAS_SKEIN_512) -BOTAN_REGISTER_NAMED_T(HashFunction, "Skein-512", Skein_512, Skein_512::make); +#if defined(BOTAN_HAS_WHIRLPOOL) + if(req.algo_name() == "Whirlpool") + { + return std::unique_ptr<HashFunction>(new Whirlpool); + } #endif -#if defined(BOTAN_HAS_WHIRLPOOL) -BOTAN_REGISTER_HASH_NOARGS(Whirlpool); +#if defined(BOTAN_HAS_PARALLEL_HASH) + if(req.algo_name() == "Parallel") + { + std::vector<std::unique_ptr<HashFunction>> hashes; + + for(size_t i = 0; i != req.arg_count(); ++i) + { + auto h = HashFunction::create(req.arg(i)); + if(!h) + { + return nullptr; + } + hashes.push_back(std::move(h)); + } + + return std::unique_ptr<HashFunction>(new Parallel(hashes)); + } #endif -#if defined(BOTAN_HAS_BLAKE2B) -BOTAN_REGISTER_NAMED_T(HashFunction, "Blake2b", Blake2b, Blake2b::make); +#if defined(BOTAN_HAS_COMB4P) + if(req.algo_name() == "Comb4p" && req.arg_count() == 2) + { + std::unique_ptr<HashFunction> h1(HashFunction::create(req.arg(0))); + std::unique_ptr<HashFunction> h2(HashFunction::create(req.arg(1))); + + if(h1 && h2) + return std::unique_ptr<HashFunction>(new Comb4P(h1.release(), h2.release())); + } #endif + + return nullptr; + } + +//static +std::unique_ptr<HashFunction> +HashFunction::create_or_throw(const std::string& algo, + const std::string& provider) + { + if(auto hash = HashFunction::create(algo, provider)) + { + return hash; + } + throw Lookup_Error("Hash", algo, provider); + } + +std::vector<std::string> HashFunction::providers(const std::string& algo_spec) + { + return probe_providers_of<HashFunction>(algo_spec, {"base", "openssl"}); + } + } + diff --git a/src/lib/hash/hash.h b/src/lib/hash/hash.h index 206333b9f..f6cf470cb 100644 --- a/src/lib/hash/hash.h +++ b/src/lib/hash/hash.h @@ -8,7 +8,6 @@ #ifndef BOTAN_HASH_FUNCTION_BASE_CLASS_H__ #define BOTAN_HASH_FUNCTION_BASE_CLASS_H__ -#include <botan/scan_name.h> #include <botan/buf_comp.h> #include <string> @@ -20,17 +19,25 @@ namespace Botan { class BOTAN_DLL HashFunction : public Buffered_Computation { public: - typedef SCAN_Name Spec; + /** + * Create an instance based on a name, or return null if the + * algo/provider combination cannot be found. If provider is + * empty then best available is chosen. + */ + static std::unique_ptr<HashFunction> + create(const std::string& algo_spec, + const std::string& provider = ""); /** * Create an instance based on a name * If provider is empty then best available is chosen. * @param algo_spec algorithm name * @param provider provider implementation to use - * @return a null pointer if the algo/provider combination cannot be found + * Throws Lookup_Error if not not found. */ - static std::unique_ptr<HashFunction> create(const std::string& algo_spec, - const std::string& provider = ""); + static std::unique_ptr<HashFunction> + create_or_throw(const std::string& algo_spec, + const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available @@ -49,9 +56,7 @@ class BOTAN_DLL HashFunction : public Buffered_Computation */ virtual std::string provider() const { return "base"; } - HashFunction(); - - virtual ~HashFunction(); + virtual ~HashFunction() {} /** * Reset the state. diff --git a/src/lib/hash/par_hash/par_hash.cpp b/src/lib/hash/par_hash/par_hash.cpp index f6bed96ee..7320afee3 100644 --- a/src/lib/hash/par_hash/par_hash.cpp +++ b/src/lib/hash/par_hash/par_hash.cpp @@ -10,23 +10,6 @@ namespace Botan { -Parallel* Parallel::make(const Spec& spec) - { - std::vector<std::unique_ptr<HashFunction>> m_hashes; - - for(size_t i = 0; i != spec.arg_count(); ++i) - { - auto h = HashFunction::create(spec.arg(i)); - if(!h) - return nullptr; - m_hashes.push_back(std::move(h)); - } - - Parallel* p = new Parallel; - std::swap(p->m_hashes, m_hashes); - return p; - } - void Parallel::add_data(const byte input[], size_t length) { for(auto&& hash : m_hashes) @@ -65,10 +48,10 @@ std::string Parallel::name() const HashFunction* Parallel::clone() const { - std::vector<HashFunction*> hash_copies; + std::vector<std::unique_ptr<HashFunction>> hash_copies; for(auto&& hash : m_hashes) - hash_copies.push_back(hash.get()); + hash_copies.push_back(std::unique_ptr<HashFunction>(hash->clone())); return new Parallel(hash_copies); } @@ -79,12 +62,11 @@ void Parallel::clear() hash->clear(); } -Parallel::Parallel(const std::vector<HashFunction*>& in) +Parallel::Parallel(std::vector<std::unique_ptr<HashFunction>>& h) { - for(size_t i = 0; i != in.size(); ++i) + for(size_t i = 0; i != h.size(); ++i) { - std::unique_ptr<HashFunction> h(in[i]->clone()); - m_hashes.push_back(std::move(h)); + m_hashes.push_back(std::unique_ptr<HashFunction>(h[i].release())); } } diff --git a/src/lib/hash/par_hash/par_hash.h b/src/lib/hash/par_hash/par_hash.h index 3a93f4e8e..67d026c2f 100644 --- a/src/lib/hash/par_hash/par_hash.h +++ b/src/lib/hash/par_hash/par_hash.h @@ -27,13 +27,12 @@ class BOTAN_DLL Parallel final : public HashFunction /** * @param hashes a set of hashes to compute in parallel + * Takes ownership of all pointers */ - explicit Parallel(const std::vector<HashFunction*>& hashes); + explicit Parallel(std::vector<std::unique_ptr<HashFunction>>& hashes); Parallel(const Parallel&) = delete; Parallel& operator=(const Parallel&) = delete; - - static Parallel* make(const Spec& spec); private: Parallel() {} diff --git a/src/lib/hash/skein/skein_512.cpp b/src/lib/hash/skein/skein_512.cpp index 86ea9e75a..21eeb1f27 100644 --- a/src/lib/hash/skein/skein_512.cpp +++ b/src/lib/hash/skein/skein_512.cpp @@ -12,11 +12,6 @@ namespace Botan { -Skein_512* Skein_512::make(const Spec& spec) - { - return new Skein_512(spec.arg_as_integer(0, 512), spec.arg(1, "")); - } - Skein_512::Skein_512(size_t arg_output_bits, const std::string& arg_personalization) : m_personalization(arg_personalization), diff --git a/src/lib/hash/skein/skein_512.h b/src/lib/hash/skein/skein_512.h index 001d9a991..1f34f1583 100644 --- a/src/lib/hash/skein/skein_512.h +++ b/src/lib/hash/skein/skein_512.h @@ -32,8 +32,6 @@ class BOTAN_DLL Skein_512 final : public HashFunction size_t hash_block_size() const override { return 64; } size_t output_length() const override { return m_output_bits / 8; } - static Skein_512* make(const Spec& spec); - HashFunction* clone() const override; std::string name() const override; void clear() override; diff --git a/src/lib/kdf/hkdf/hkdf.cpp b/src/lib/kdf/hkdf/hkdf.cpp index 56dc72f09..13d5832d2 100644 --- a/src/lib/kdf/hkdf/hkdf.cpp +++ b/src/lib/kdf/hkdf/hkdf.cpp @@ -9,17 +9,6 @@ namespace Botan { -HKDF* HKDF::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new HKDF(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new HKDF(mac.release()); - - return nullptr; - } - size_t HKDF::kdf(byte out[], size_t out_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, diff --git a/src/lib/kdf/hkdf/hkdf.h b/src/lib/kdf/hkdf/hkdf.h index ea17f8c01..54ecc5283 100644 --- a/src/lib/kdf/hkdf/hkdf.h +++ b/src/lib/kdf/hkdf/hkdf.h @@ -27,8 +27,6 @@ class BOTAN_DLL HKDF final : public KDF */ explicit HKDF(MessageAuthenticationCode* prf) : m_prf(prf) {} - static HKDF* make(const Spec& spec); - KDF* clone() const override { return new HKDF(m_prf->clone()); } std::string name() const override { return "HKDF(" + m_prf->name() + ")"; } diff --git a/src/lib/kdf/kdf.cpp b/src/lib/kdf/kdf.cpp index 66296bf96..f8f822809 100644 --- a/src/lib/kdf/kdf.cpp +++ b/src/lib/kdf/kdf.cpp @@ -6,8 +6,8 @@ */ #include <botan/kdf.h> +#include <botan/scan_name.h> #include <botan/exceptn.h> -#include <botan/internal/algo_registry.h> #if defined(BOTAN_HAS_HKDF) #include <botan/hkdf.h> @@ -45,77 +45,176 @@ #include <botan/sp800_56c.h> #endif -#define BOTAN_REGISTER_KDF_NOARGS(type, name) \ - BOTAN_REGISTER_NAMED_T(KDF, name, type, (make_new_T<type>)) -#define BOTAN_REGISTER_KDF_1HASH(type, name) \ - BOTAN_REGISTER_NAMED_T(KDF, name, type, (make_new_T_1X<type, HashFunction>)) - -#define BOTAN_REGISTER_KDF_NAMED_1STR(type, name) \ - BOTAN_REGISTER_NAMED_T(KDF, name, type, (make_new_T_1str_req<type>)) - namespace Botan { -KDF::~KDF() {} +namespace { -std::unique_ptr<KDF> KDF::create(const std::string& algo_spec, - const std::string& provider) +template<typename KDF_Type> +std::unique_ptr<KDF> +kdf_create_mac_or_hash(const std::string& nm) { - return std::unique_ptr<KDF>(make_a<KDF>(Botan::KDF::Spec(algo_spec), provider)); - } + if(auto mac = MessageAuthenticationCode::create(nm)) + return std::unique_ptr<KDF>(new KDF_Type(mac.release())); -std::vector<std::string> KDF::providers(const std::string& algo_spec) - { - return providers_of<KDF>(KDF::Spec(algo_spec)); - } + if(auto mac = MessageAuthenticationCode::create("HMAC(" + nm + ")")) + return std::unique_ptr<KDF>(new KDF_Type(mac.release())); -KDF* get_kdf(const std::string& algo_spec) - { - SCAN_Name request(algo_spec); + return nullptr; + } - if(request.algo_name() == "Raw") - return nullptr; // No KDF +} - auto kdf = KDF::create(algo_spec); - if(!kdf) - throw Algorithm_Not_Found(algo_spec); - return kdf.release(); - } +std::unique_ptr<KDF> KDF::create(const std::string& algo_spec, + const std::string& provider) + { + const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_HKDF) -BOTAN_REGISTER_NAMED_T(KDF, "HKDF", HKDF, HKDF::make); -#endif - -#if defined(BOTAN_HAS_KDF1) -BOTAN_REGISTER_KDF_1HASH(KDF1, "KDF1"); + if(req.algo_name() == "HKDF" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<HKDF>(req.arg(0)); + } + } #endif #if defined(BOTAN_HAS_KDF2) -BOTAN_REGISTER_KDF_1HASH(KDF2, "KDF2"); + if(req.algo_name() == "KDF2" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto hash = HashFunction::create(req.arg(0))) + return std::unique_ptr<KDF>(new KDF2(hash.release())); + } + } #endif #if defined(BOTAN_HAS_KDF1_18033) -BOTAN_REGISTER_KDF_1HASH( KDF1_18033, "KDF1-18033" ); + if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto hash = HashFunction::create(req.arg(0))) + return std::unique_ptr<KDF>(new KDF1_18033(hash.release())); + } + } +#endif + +#if defined(BOTAN_HAS_KDF1) + if(req.algo_name() == "KDF1" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto hash = HashFunction::create(req.arg(0))) + return std::unique_ptr<KDF>(new KDF1(hash.release())); + } + } #endif #if defined(BOTAN_HAS_TLS_V10_PRF) -BOTAN_REGISTER_KDF_NOARGS(TLS_PRF, "TLS-PRF"); + if(req.algo_name() == "TLS-PRF" && req.arg_count() == 0) + { + if(provider.empty() || provider == "base") + { + return std::unique_ptr<KDF>(new TLS_PRF); + } + } #endif #if defined(BOTAN_HAS_TLS_V12_PRF) -BOTAN_REGISTER_NAMED_T(KDF, "TLS-12-PRF", TLS_12_PRF, TLS_12_PRF::make); + if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0)); + } + } #endif #if defined(BOTAN_HAS_X942_PRF) -BOTAN_REGISTER_KDF_NAMED_1STR(X942_PRF, "X9.42-PRF"); + if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return std::unique_ptr<KDF>(new X942_PRF(req.arg(0))); + } + } #endif #if defined(BOTAN_HAS_SP800_108) -BOTAN_REGISTER_NAMED_T(KDF, "SP800-108-Counter", SP800_108_Counter, SP800_108_Counter::make); -BOTAN_REGISTER_NAMED_T(KDF, "SP800-108-Feedback", SP800_108_Feedback, SP800_108_Feedback::make); -BOTAN_REGISTER_NAMED_T(KDF, "SP800-108-Pipeline", SP800_108_Pipeline, SP800_108_Pipeline::make); + if(req.algo_name() == "SP800-108-Counter" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<SP800_108_Counter>(req.arg(0)); + } + } + + if(req.algo_name() == "SP800-108-Feedback" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0)); + } + } + + if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + return kdf_create_mac_or_hash<SP800_108_Pipeline>(req.arg(0)); + } + } #endif #if defined(BOTAN_HAS_SP800_56C) -BOTAN_REGISTER_NAMED_T(KDF, "SP800-56C", SP800_56C, SP800_56C::make); + if(req.algo_name() == "SP800-56C" && req.arg_count() == 1) + { + std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0))); + if(exp) + { + if(auto mac = MessageAuthenticationCode::create(req.arg(0))) + return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release())); + + if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")")) + return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release())); + } + } #endif + + return nullptr; + } + +//static +std::unique_ptr<KDF> +KDF::create_or_throw(const std::string& algo, + const std::string& provider) + { + if(auto bc = KDF::create(algo, provider)) + { + return bc; + } + throw Lookup_Error("Block cipher", algo, provider); + } + +std::vector<std::string> KDF::providers(const std::string& algo_spec) + { + return probe_providers_of<KDF>(algo_spec, { "base" }); + } + +KDF* get_kdf(const std::string& algo_spec) + { + SCAN_Name request(algo_spec); + + if(request.algo_name() == "Raw") + return nullptr; // No KDF + + //return KDF::create_or_throw(algo_spec).release(); + auto kdf = KDF::create(algo_spec); + if(!kdf) + throw Algorithm_Not_Found(algo_spec); + return kdf.release(); + } + } diff --git a/src/lib/kdf/kdf.h b/src/lib/kdf/kdf.h index f9acb9d38..15336a966 100644 --- a/src/lib/kdf/kdf.h +++ b/src/lib/kdf/kdf.h @@ -8,7 +8,6 @@ #ifndef BOTAN_KDF_BASE_H__ #define BOTAN_KDF_BASE_H__ -#include <botan/scan_name.h> #include <botan/secmem.h> #include <botan/types.h> #include <string> @@ -21,7 +20,7 @@ namespace Botan { class BOTAN_DLL KDF { public: - virtual ~KDF(); + virtual ~KDF() {} /** * Create an instance based on a name @@ -30,8 +29,18 @@ class BOTAN_DLL KDF * @param provider provider implementation to choose * @return a null pointer if the algo/provider combination cannot be found */ - static std::unique_ptr<KDF> create(const std::string& algo_spec, - const std::string& provider = ""); + static std::unique_ptr<KDF> + create(const std::string& algo_spec, + const std::string& provider = ""); + + /** + * Create an instance based on a name, or throw if the + * algo/provider combination cannot be found. If provider is + * empty then best available is chosen. + */ + static std::unique_ptr<KDF> + create_or_throw(const std::string& algo_spec, + const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available @@ -173,8 +182,6 @@ class BOTAN_DLL KDF * @return new object representing the same algorithm as *this */ virtual KDF* clone() const = 0; - - typedef SCAN_Name Spec; }; /** diff --git a/src/lib/kdf/prf_tls/prf_tls.cpp b/src/lib/kdf/prf_tls/prf_tls.cpp index 14b330901..e83d07692 100644 --- a/src/lib/kdf/prf_tls/prf_tls.cpp +++ b/src/lib/kdf/prf_tls/prf_tls.cpp @@ -10,17 +10,6 @@ namespace Botan { -TLS_12_PRF* TLS_12_PRF::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new TLS_12_PRF(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new TLS_12_PRF(mac.release()); - - return nullptr; - } - TLS_PRF::TLS_PRF() : m_hmac_md5(MessageAuthenticationCode::create("HMAC(MD5)")), m_hmac_sha1(MessageAuthenticationCode::create("HMAC(SHA-1)")) diff --git a/src/lib/kdf/prf_tls/prf_tls.h b/src/lib/kdf/prf_tls/prf_tls.h index 58cd5758e..64891144a 100644 --- a/src/lib/kdf/prf_tls/prf_tls.h +++ b/src/lib/kdf/prf_tls/prf_tls.h @@ -53,8 +53,6 @@ class BOTAN_DLL TLS_12_PRF final : public KDF * @param mac MAC algorithm to use */ explicit TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {} - - static TLS_12_PRF* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_mac; }; diff --git a/src/lib/kdf/sp800_108/sp800_108.cpp b/src/lib/kdf/sp800_108/sp800_108.cpp index aafb349b2..77973600a 100644 --- a/src/lib/kdf/sp800_108/sp800_108.cpp +++ b/src/lib/kdf/sp800_108/sp800_108.cpp @@ -12,17 +12,6 @@ namespace Botan { -SP800_108_Counter* SP800_108_Counter::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new SP800_108_Counter(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new SP800_108_Counter(mac.release()); - - return nullptr; - } - size_t SP800_108_Counter::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, @@ -65,17 +54,6 @@ size_t SP800_108_Counter::kdf(byte key[], size_t key_len, return key_len; } -SP800_108_Feedback* SP800_108_Feedback::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new SP800_108_Feedback(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new SP800_108_Feedback(mac.release()); - - return nullptr; - } - size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, @@ -122,17 +100,6 @@ size_t SP800_108_Feedback::kdf(byte key[], size_t key_len, return key_len; } -SP800_108_Pipeline* SP800_108_Pipeline::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new SP800_108_Pipeline(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new SP800_108_Pipeline(mac.release()); - - return nullptr; - } - size_t SP800_108_Pipeline::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, diff --git a/src/lib/kdf/sp800_108/sp800_108.h b/src/lib/kdf/sp800_108/sp800_108.h index 2d4d028b2..e368457b4 100644 --- a/src/lib/kdf/sp800_108/sp800_108.h +++ b/src/lib/kdf/sp800_108/sp800_108.h @@ -49,8 +49,6 @@ class BOTAN_DLL SP800_108_Counter : public KDF * @param mac MAC algorithm to use */ SP800_108_Counter(MessageAuthenticationCode* mac) : m_prf(mac) {} - - static SP800_108_Counter* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_prf; }; @@ -88,8 +86,6 @@ class BOTAN_DLL SP800_108_Feedback : public KDF const byte label[], size_t label_len) const override; SP800_108_Feedback(MessageAuthenticationCode* mac) : m_prf(mac) {} - - static SP800_108_Feedback* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_prf; }; @@ -128,7 +124,6 @@ class BOTAN_DLL SP800_108_Pipeline : public KDF SP800_108_Pipeline(MessageAuthenticationCode* mac) : m_prf(mac) {} - static SP800_108_Pipeline* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_prf; }; diff --git a/src/lib/kdf/sp800_56c/sp800_56c.cpp b/src/lib/kdf/sp800_56c/sp800_56c.cpp index 338feba2a..f6d01ec2f 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.cpp +++ b/src/lib/kdf/sp800_56c/sp800_56c.cpp @@ -11,20 +11,6 @@ namespace Botan { -SP800_56C* SP800_56C::make(const Spec& spec) - { - if(auto exp = SP800_108_Feedback::make(spec)) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new SP800_56C(mac.release(), exp); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new SP800_56C(mac.release(), exp); - } - - return nullptr; - } - size_t SP800_56C::kdf(byte key[], size_t key_len, const byte secret[], size_t secret_len, const byte salt[], size_t salt_len, diff --git a/src/lib/kdf/sp800_56c/sp800_56c.h b/src/lib/kdf/sp800_56c/sp800_56c.h index 83f11906a..5c5acb075 100644 --- a/src/lib/kdf/sp800_56c/sp800_56c.h +++ b/src/lib/kdf/sp800_56c/sp800_56c.h @@ -50,8 +50,6 @@ class BOTAN_DLL SP800_56C : public KDF * @param exp KDF used for key expansion */ SP800_56C(MessageAuthenticationCode* mac, KDF* exp) : m_prf(mac), m_exp(exp) {} - - static SP800_56C* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_prf; std::unique_ptr<KDF> m_exp; diff --git a/src/lib/mac/cbc_mac/cbc_mac.cpp b/src/lib/mac/cbc_mac/cbc_mac.cpp index 449865255..741d550e5 100644 --- a/src/lib/mac/cbc_mac/cbc_mac.cpp +++ b/src/lib/mac/cbc_mac/cbc_mac.cpp @@ -9,16 +9,6 @@ namespace Botan { -CBC_MAC* CBC_MAC::make(const Spec& spec) - { - if(spec.arg_count() == 1) - { - if(auto bc = BlockCipher::create(spec.arg(0))) - return new CBC_MAC(bc.release()); - } - return nullptr; - } - /* * Update an CBC-MAC Calculation */ diff --git a/src/lib/mac/cbc_mac/cbc_mac.h b/src/lib/mac/cbc_mac/cbc_mac.h index 4a3dece95..dd4877d1c 100644 --- a/src/lib/mac/cbc_mac/cbc_mac.h +++ b/src/lib/mac/cbc_mac/cbc_mac.h @@ -33,8 +33,6 @@ class BOTAN_DLL CBC_MAC final : public MessageAuthenticationCode * @param cipher the block cipher to use */ explicit CBC_MAC(BlockCipher* cipher); - - static CBC_MAC* make(const Spec& spec); private: void add_data(const byte[], size_t) override; void final_result(byte[]) override; diff --git a/src/lib/mac/cmac/cmac.cpp b/src/lib/mac/cmac/cmac.cpp index 1501bc316..9afd86cdb 100644 --- a/src/lib/mac/cmac/cmac.cpp +++ b/src/lib/mac/cmac/cmac.cpp @@ -9,16 +9,6 @@ namespace Botan { -CMAC* CMAC::make(const Spec& spec) - { - if(spec.arg_count() == 1) - { - if(auto bc = BlockCipher::create(spec.arg(0))) - return new CMAC(bc.release()); - } - return nullptr; - } - /* * Perform CMAC's multiplication in GF(2^n) */ diff --git a/src/lib/mac/cmac/cmac.h b/src/lib/mac/cmac/cmac.h index fac754e62..6897665c0 100644 --- a/src/lib/mac/cmac/cmac.h +++ b/src/lib/mac/cmac/cmac.h @@ -41,8 +41,6 @@ class BOTAN_DLL CMAC final : public MessageAuthenticationCode */ explicit CMAC(BlockCipher* cipher); - static CMAC* make(const Spec& spec); - CMAC(const CMAC&) = delete; CMAC& operator=(const CMAC&) = delete; private: diff --git a/src/lib/mac/hmac/hmac.cpp b/src/lib/mac/hmac/hmac.cpp index f445ab0cf..a2021515f 100644 --- a/src/lib/mac/hmac/hmac.cpp +++ b/src/lib/mac/hmac/hmac.cpp @@ -10,16 +10,6 @@ namespace Botan { -HMAC* HMAC::make(const Spec& spec) - { - if(spec.arg_count() == 1) - { - if(auto h = HashFunction::create(spec.arg(0))) - return new HMAC(h.release()); - } - return nullptr; - } - /* * Update a HMAC Calculation */ diff --git a/src/lib/mac/hmac/hmac.h b/src/lib/mac/hmac/hmac.h index 654a167e7..bfb425fa8 100644 --- a/src/lib/mac/hmac/hmac.h +++ b/src/lib/mac/hmac/hmac.h @@ -36,8 +36,6 @@ class BOTAN_DLL HMAC final : public MessageAuthenticationCode */ explicit HMAC(HashFunction* hash); - static HMAC* make(const Spec& spec); - HMAC(const HMAC&) = delete; HMAC& operator=(const HMAC&) = delete; private: diff --git a/src/lib/mac/mac.cpp b/src/lib/mac/mac.cpp index a3917141d..70807b39f 100644 --- a/src/lib/mac/mac.cpp +++ b/src/lib/mac/mac.cpp @@ -6,7 +6,7 @@ */ #include <botan/mac.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #include <botan/mem_ops.h> #if defined(BOTAN_HAS_CBC_MAC) @@ -35,18 +35,97 @@ namespace Botan { -std::unique_ptr<MessageAuthenticationCode> MessageAuthenticationCode::create(const std::string& algo_spec, - const std::string& provider) +std::unique_ptr<MessageAuthenticationCode> +MessageAuthenticationCode::create(const std::string& algo_spec, + const std::string& provider) { - return std::unique_ptr<MessageAuthenticationCode>(make_a<MessageAuthenticationCode>(MessageAuthenticationCode::Spec(algo_spec), provider)); + const SCAN_Name req(algo_spec); + +#if defined(BOTAN_HAS_HMAC) + if(req.algo_name() == "HMAC" && req.arg_count() == 1) + { + // TODO OpenSSL + if(provider.empty() || provider == "base") + { + if(auto h = HashFunction::create(req.arg(0))) + return std::unique_ptr<MessageAuthenticationCode>(new HMAC(h.release())); + } + } +#endif + +#if defined(BOTAN_HAS_POLY1305) + if(req.algo_name() == "Poly1305" && req.arg_count() == 0) + { + if(provider.empty() || provider == "base") + return std::unique_ptr<MessageAuthenticationCode>(new Poly1305); + } +#endif + +#if defined(BOTAN_HAS_SIPHASH) + if(req.algo_name() == "SipHash") + { + if(provider.empty() || provider == "base") + { + return std::unique_ptr<MessageAuthenticationCode>( + new SipHash(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4))); + } + } +#endif + +#if defined(BOTAN_HAS_CMAC) + if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1) + { + // TODO: OpenSSL CMAC + if(provider.empty() || provider == "base") + { + if(auto bc = BlockCipher::create(req.arg(0))) + return std::unique_ptr<MessageAuthenticationCode>(new CMAC(bc.release())); + } + } +#endif + + +#if defined(BOTAN_HAS_CBC_MAC) + if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto bc = BlockCipher::create(req.arg(0))) + return std::unique_ptr<MessageAuthenticationCode>(new CBC_MAC(bc.release())); + } + } +#endif + +#if defined(BOTAN_HAS_ANSI_X919_MAC) + if(req.algo_name() == "X9.19-MAC") + { + if(provider.empty() || provider == "base") + { + return std::unique_ptr<MessageAuthenticationCode>(new ANSI_X919_MAC); + } + } +#endif + + return nullptr; } -std::vector<std::string> MessageAuthenticationCode::providers(const std::string& algo_spec) +std::vector<std::string> +MessageAuthenticationCode::providers(const std::string& algo_spec) { - return providers_of<MessageAuthenticationCode>(MessageAuthenticationCode::Spec(algo_spec)); + return probe_providers_of<MessageAuthenticationCode>(algo_spec, {"base", "openssl"}); } -MessageAuthenticationCode::~MessageAuthenticationCode() {} +//static +std::unique_ptr<MessageAuthenticationCode> +MessageAuthenticationCode::create_or_throw(const std::string& algo, + const std::string& provider) + { + if(auto mac = MessageAuthenticationCode::create(algo, provider)) + { + return mac; + } + throw Lookup_Error("MAC", algo, provider); + } /* * Default (deterministic) MAC verification operation @@ -61,28 +140,4 @@ bool MessageAuthenticationCode::verify_mac(const byte mac[], size_t length) return same_mem(our_mac.data(), mac, length); } -#if defined(BOTAN_HAS_CBC_MAC) -BOTAN_REGISTER_NAMED_T(MessageAuthenticationCode, "CBC-MAC", CBC_MAC, CBC_MAC::make); -#endif - -#if defined(BOTAN_HAS_CMAC) -BOTAN_REGISTER_NAMED_T(MessageAuthenticationCode, "CMAC", CMAC, CMAC::make); -#endif - -#if defined(BOTAN_HAS_HMAC) -BOTAN_REGISTER_NAMED_T(MessageAuthenticationCode, "HMAC", HMAC, HMAC::make); -#endif - -#if defined(BOTAN_HAS_POLY1305) -BOTAN_REGISTER_T_NOARGS(MessageAuthenticationCode, Poly1305); -#endif - -#if defined(BOTAN_HAS_SIPHASH) -BOTAN_REGISTER_NAMED_T_2LEN(MessageAuthenticationCode, SipHash, "SipHash", "base", 2, 4); -#endif - -#if defined(BOTAN_HAS_ANSI_X919_MAC) -BOTAN_REGISTER_NAMED_T(MessageAuthenticationCode, "X9.19-MAC", ANSI_X919_MAC, make_new_T<ANSI_X919_MAC>); -#endif - } diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h index 69b7ea581..f3befc512 100644 --- a/src/lib/mac/mac.h +++ b/src/lib/mac/mac.h @@ -10,7 +10,6 @@ #include <botan/buf_comp.h> #include <botan/sym_algo.h> -#include <botan/scan_name.h> #include <string> namespace Botan { @@ -22,8 +21,6 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation, public SymmetricAlgorithm { public: - typedef SCAN_Name Spec; - /** * Create an instance based on a name * If provider is empty then best available is chosen. @@ -31,15 +28,27 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation, * @param provider provider implementation to use * @return a null pointer if the algo/provider combination cannot be found */ - static std::unique_ptr<MessageAuthenticationCode> create(const std::string& algo_spec, - const std::string& provider = ""); + static std::unique_ptr<MessageAuthenticationCode> + create(const std::string& algo_spec, + const std::string& provider = ""); + + /* + * Create an instance based on a name + * If provider is empty then best available is chosen. + * @param algo_spec algorithm name + * @param provider provider implementation to use + * Throws a Lookup_Error if algo/provider combination cannot be found + */ + static std::unique_ptr<MessageAuthenticationCode> + create_or_throw(const std::string& algo_spec, + const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available */ static std::vector<std::string> providers(const std::string& algo_spec); - virtual ~MessageAuthenticationCode(); + virtual ~MessageAuthenticationCode() {} /** * Verify a MAC. diff --git a/src/lib/modes/aead/aead.cpp b/src/lib/modes/aead/aead.cpp index 88e6cbeaa..1b7b78be7 100644 --- a/src/lib/modes/aead/aead.cpp +++ b/src/lib/modes/aead/aead.cpp @@ -5,8 +5,12 @@ */ #include <botan/aead.h> -#include <botan/internal/mode_utils.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> +#include <sstream> + +#if defined(BOTAN_HAS_BLOCK_CIPHER) + #include <botan/block_cipher.h> +#endif #if defined(BOTAN_HAS_AEAD_CCM) #include <botan/ccm.h> @@ -34,42 +38,113 @@ namespace Botan { -AEAD_Mode::~AEAD_Mode() {} +AEAD_Mode* get_aead(const std::string& algo, Cipher_Dir dir) + { +#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) + if(algo == "ChaCha20Poly1305") + { + if(dir == ENCRYPTION) + return new ChaCha20Poly1305_Encryption; + else + return new ChaCha20Poly1305_Decryption; -#if defined(BOTAN_HAS_AEAD_CCM) -BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(CCM_Encryption, CCM_Decryption, 16, 3); + } #endif -#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) -BOTAN_REGISTER_T_NOARGS(Cipher_Mode, ChaCha20Poly1305_Encryption); -BOTAN_REGISTER_T_NOARGS(Cipher_Mode, ChaCha20Poly1305_Decryption); -#endif + if(algo.find('/') != std::string::npos) + { + const std::vector<std::string> algo_parts = split_on(algo, '/'); + const std::string cipher_name = algo_parts[0]; + const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); -#if defined(BOTAN_HAS_AEAD_EAX) -BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(EAX_Encryption, EAX_Decryption, 0); + if(mode_info.empty()) + return nullptr; + + std::ostringstream alg_args; + + alg_args << '(' << cipher_name; + for(size_t i = 1; i < mode_info.size(); ++i) + alg_args << ',' << mode_info[i]; + for(size_t i = 2; i < algo_parts.size(); ++i) + alg_args << ',' << algo_parts[i]; + alg_args << ')'; + + const std::string mode_name = mode_info[0] + alg_args.str(); + return get_aead(mode_name, dir); + } + +#if defined(BOTAN_HAS_BLOCK_CIPHER) + + SCAN_Name req(algo); + + if(req.arg_count() == 0) + { + return nullptr; + } + + std::unique_ptr<BlockCipher> bc(BlockCipher::create(req.arg(0))); + + if(!bc) + { + return nullptr; + } + +#if defined(BOTAN_HAS_AEAD_CCM) + if(req.algo_name() == "CCM") + { + size_t tag_len = req.arg_as_integer(1, 16); + size_t L_len = req.arg_as_integer(2, 3); + if(dir == ENCRYPTION) + return new CCM_Encryption(bc.release(), tag_len, L_len); + else + return new CCM_Decryption(bc.release(), tag_len, L_len); + } #endif #if defined(BOTAN_HAS_AEAD_GCM) -BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(GCM_Encryption, GCM_Decryption, 16); + if(req.algo_name() == "GCM") + { + size_t tag_len = req.arg_as_integer(1, 16); + if(dir == ENCRYPTION) + return new GCM_Encryption(bc.release(), tag_len); + else + return new GCM_Decryption(bc.release(), tag_len); + } #endif #if defined(BOTAN_HAS_AEAD_OCB) -BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(OCB_Encryption, OCB_Decryption, 16); + if(req.algo_name() == "OCB") + { + size_t tag_len = req.arg_as_integer(1, 16); + if(dir == ENCRYPTION) + return new OCB_Encryption(bc.release(), tag_len); + else + return new OCB_Decryption(bc.release(), tag_len); + } #endif -#if defined(BOTAN_HAS_AEAD_SIV) -BOTAN_REGISTER_BLOCK_CIPHER_MODE(SIV_Encryption, SIV_Decryption); +#if defined(BOTAN_HAS_AEAD_EAX) + if(req.algo_name() == "EAX") + { + size_t tag_len = req.arg_as_integer(1, bc->block_size()); + if(dir == ENCRYPTION) + return new EAX_Encryption(bc.release(), tag_len); + else + return new EAX_Decryption(bc.release(), tag_len); + } #endif -AEAD_Mode* get_aead(const std::string& algo_spec, Cipher_Dir direction) - { - std::unique_ptr<Cipher_Mode> mode(get_cipher_mode(algo_spec, direction)); - - if(AEAD_Mode* aead = dynamic_cast<AEAD_Mode*>(mode.get())) +#if defined(BOTAN_HAS_AEAD_SIV) + if(req.algo_name() == "SIV") { - mode.release(); - return aead; + if(dir == ENCRYPTION) + return new SIV_Encryption(bc.release()); + else + return new SIV_Decryption(bc.release()); } +#endif + +#endif return nullptr; } diff --git a/src/lib/modes/aead/aead.h b/src/lib/modes/aead/aead.h index 0769a1829..2cdc6137e 100644 --- a/src/lib/modes/aead/aead.h +++ b/src/lib/modes/aead/aead.h @@ -74,7 +74,7 @@ class BOTAN_DLL AEAD_Mode : public Cipher_Mode */ size_t default_nonce_length() const override { return 12; } - virtual ~AEAD_Mode(); + virtual ~AEAD_Mode() {} }; /** diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp index d5559bfb5..81b9f4943 100644 --- a/src/lib/modes/aead/ccm/ccm.cpp +++ b/src/lib/modes/aead/ccm/ccm.cpp @@ -5,7 +5,6 @@ * 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> diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp index 04326dede..d2f16c225 100644 --- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp +++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp @@ -6,7 +6,6 @@ */ #include <botan/chacha20poly1305.h> -#include <botan/internal/mode_utils.h> namespace Botan { diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp index f26a1eae3..c76f15b48 100644 --- a/src/lib/modes/aead/eax/eax.cpp +++ b/src/lib/modes/aead/eax/eax.cpp @@ -5,7 +5,6 @@ * 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> diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index 32c6c0b70..a73e5ee5b 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -6,8 +6,8 @@ */ #include <botan/gcm.h> -#include <botan/internal/mode_utils.h> #include <botan/internal/ct_utils.h> +#include <botan/loadstor.h> #include <botan/ctr.h> #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 e21749f3b..0ce2b6f00 100644 --- a/src/lib/modes/aead/ocb/ocb.cpp +++ b/src/lib/modes/aead/ocb/ocb.cpp @@ -5,9 +5,9 @@ * 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/bit_ops.h> namespace Botan { diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp index 5f8c13f7f..ce20f3ada 100644 --- a/src/lib/modes/aead/siv/siv.cpp +++ b/src/lib/modes/aead/siv/siv.cpp @@ -5,7 +5,6 @@ * 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> diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp index 8066dae12..7e1fe4d0f 100644 --- a/src/lib/modes/cbc/cbc.cpp +++ b/src/lib/modes/cbc/cbc.cpp @@ -5,9 +5,9 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/mode_utils.h> #include <botan/cbc.h> #include <botan/mode_pad.h> +#include <botan/internal/rounding.h> namespace Botan { diff --git a/src/lib/modes/cfb/cfb.cpp b/src/lib/modes/cfb/cfb.cpp index cc5e9bae7..793bfaf46 100644 --- a/src/lib/modes/cfb/cfb.cpp +++ b/src/lib/modes/cfb/cfb.cpp @@ -5,7 +5,6 @@ * 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> diff --git a/src/lib/modes/cipher_mode.cpp b/src/lib/modes/cipher_mode.cpp index e7040772c..d622e7754 100644 --- a/src/lib/modes/cipher_mode.cpp +++ b/src/lib/modes/cipher_mode.cpp @@ -7,10 +7,17 @@ #include <botan/cipher_mode.h> #include <botan/stream_mode.h> -#include <botan/internal/mode_utils.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #include <sstream> +#if defined(BOTAN_HAS_BLOCK_CIPHER) + #include <botan/block_cipher.h> +#endif + +#if defined(BOTAN_HAS_AEAD_MODES) + #include <botan/aead.h> +#endif + #if defined(BOTAN_HAS_MODE_ECB) #include <botan/ecb.h> #endif @@ -27,126 +34,127 @@ #include <botan/xts.h> #endif -namespace Botan { - -#define BOTAN_REGISTER_CIPHER_MODE(name, maker) BOTAN_REGISTER_T(Cipher_Mode, name, maker) -#define BOTAN_REGISTER_CIPHER_MODE_NOARGS(name) BOTAN_REGISTER_T_NOARGS(Cipher_Mode, name) - -#if defined(BOTAN_HAS_MODE_ECB) - -template<typename T> -Cipher_Mode* make_ecb_mode(const Cipher_Mode::Spec& spec) - { - std::unique_ptr<BlockCipher> bc(BlockCipher::create(spec.arg(0))); - std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(spec.arg(1, "NoPadding"))); - if(bc && pad) - return new T(bc.release(), pad.release()); - return nullptr; - } - -BOTAN_REGISTER_CIPHER_MODE(ECB_Encryption, make_ecb_mode<ECB_Encryption>); -BOTAN_REGISTER_CIPHER_MODE(ECB_Decryption, make_ecb_mode<ECB_Decryption>); +#if defined(BOTAN_HAS_MODE_XTS) + #include <botan/xts.h> #endif -#if defined(BOTAN_HAS_MODE_CBC) +namespace Botan { -template<typename CBC_T, typename CTS_T> -Cipher_Mode* make_cbc_mode(const Cipher_Mode::Spec& spec) +Cipher_Mode* get_cipher_mode(const std::string& algo, Cipher_Dir direction) { - std::unique_ptr<BlockCipher> bc(BlockCipher::create(spec.arg(0))); - - if(bc) + if(auto sc = StreamCipher::create(algo)) { - const std::string padding = spec.arg(1, "PKCS7"); - - if(padding == "CTS") - return new CTS_T(bc.release()); - else - return new CBC_T(bc.release(), get_bc_pad(padding)); + return new Stream_Cipher_Mode(sc.release()); } - return nullptr; - } - -BOTAN_REGISTER_CIPHER_MODE(CBC_Encryption, (make_cbc_mode<CBC_Encryption,CTS_Encryption>)); -BOTAN_REGISTER_CIPHER_MODE(CBC_Decryption, (make_cbc_mode<CBC_Decryption,CTS_Decryption>)); -#endif - -#if defined(BOTAN_HAS_MODE_CFB) -BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(CFB_Encryption, CFB_Decryption, 0); -#endif - -#if defined(BOTAN_HAS_MODE_XTS) -BOTAN_REGISTER_BLOCK_CIPHER_MODE(XTS_Encryption, XTS_Decryption); +#if defined(BOTAN_HAS_AEAD_MODES) + if(auto aead = get_aead(algo, direction)) + { + return aead; + } #endif -Cipher_Mode* get_cipher_mode(const std::string& algo_spec, Cipher_Dir direction) - { - const std::string provider = ""; + if(algo.find('/') != std::string::npos) + { + const std::vector<std::string> algo_parts = split_on(algo, '/'); + const std::string cipher_name = algo_parts[0]; + const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); - const char* dir_string = (direction == ENCRYPTION) ? "_Encryption" : "_Decryption"; + if(mode_info.empty()) + return nullptr; - Cipher_Mode::Spec spec(algo_spec, dir_string); + std::ostringstream alg_args; - std::unique_ptr<Cipher_Mode> cipher_mode( - Algo_Registry<Cipher_Mode>::global_registry().make( - Cipher_Mode::Spec(algo_spec, dir_string), - provider) - ); + alg_args << '(' << cipher_name; + for(size_t i = 1; i < mode_info.size(); ++i) + alg_args << ',' << mode_info[i]; + for(size_t i = 2; i < algo_parts.size(); ++i) + alg_args << ',' << algo_parts[i]; + alg_args << ')'; - if(cipher_mode) - { - return cipher_mode.release(); + const std::string mode_name = mode_info[0] + alg_args.str(); + return get_cipher_mode(mode_name, direction); } - const std::vector<std::string> algo_parts = split_on(algo_spec, '/'); - if(algo_parts.size() < 2) - return nullptr; +#if defined(BOTAN_HAS_BLOCK_CIPHER) - const std::string cipher_name = algo_parts[0]; - const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]); + SCAN_Name spec(algo); - if(mode_info.empty()) + if(spec.arg_count() == 0) + { return nullptr; + } - std::ostringstream alg_args; + std::unique_ptr<BlockCipher> bc(BlockCipher::create(spec.arg(0))); - alg_args << '(' << cipher_name; - for(size_t i = 1; i < mode_info.size(); ++i) - alg_args << ',' << mode_info[i]; - for(size_t i = 2; i < algo_parts.size(); ++i) - alg_args << ',' << algo_parts[i]; - alg_args << ')'; + if(!bc) + { + return nullptr; + } - const std::string mode_name = mode_info[0] + alg_args.str(); - const std::string mode_name_directional = mode_info[0] + dir_string + alg_args.str(); +#if defined(BOTAN_HAS_MODE_CBC) + if(spec.algo_name() == "CBC") + { + const std::string padding = spec.arg(1, "PKCS7"); - cipher_mode.reset( - Algo_Registry<Cipher_Mode>::global_registry().make( - Cipher_Mode::Spec(mode_name_directional), - provider) - ); + if(padding == "CTS") + { + if(direction == ENCRYPTION) + return new CTS_Encryption(bc.release()); + else + return new CTS_Decryption(bc.release()); + } + else + { + std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(padding)); + + if(pad) + { + if(direction == ENCRYPTION) + return new CBC_Encryption(bc.release(), pad.release()); + else + return new CBC_Decryption(bc.release(), pad.release()); + } + } + } +#endif - if(cipher_mode) +#if defined(BOTAN_HAS_MODE_XTS) + if(spec.algo_name() == "XTS") { - return cipher_mode.release(); + if(direction == ENCRYPTION) + return new XTS_Encryption(bc.release()); + else + return new XTS_Decryption(bc.release()); } +#endif - cipher_mode.reset( - Algo_Registry<Cipher_Mode>::global_registry().make( - Cipher_Mode::Spec(mode_name), - provider) - ); - - if(cipher_mode) +#if defined(BOTAN_HAS_MODE_CFB) + if(spec.algo_name() == "CFB") { - return cipher_mode.release(); + const size_t feedback_bits = spec.arg_as_integer(1, 8*bc->block_size()); + if(direction == ENCRYPTION) + return new CFB_Encryption(bc.release(), feedback_bits); + else + return new CFB_Decryption(bc.release(), feedback_bits); } +#endif - if(auto sc = StreamCipher::create(mode_name, provider)) +#if defined(BOTAN_HAS_MODE_ECB) + if(spec.algo_name() == "ECB") { - return new Stream_Cipher_Mode(sc.release()); + std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(spec.arg(1, "NoPadding"))); + if(pad) + { + if(direction == ENCRYPTION) + return new ECB_Encryption(bc.release(), pad.release()); + else + return new ECB_Decryption(bc.release(), pad.release()); + } } +#endif + +#endif return nullptr; } diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h index f08989a9e..7c0f8fc57 100644 --- a/src/lib/modes/cipher_mode.h +++ b/src/lib/modes/cipher_mode.h @@ -12,7 +12,6 @@ #include <botan/key_spec.h> #include <botan/exceptn.h> #include <botan/symkey.h> -#include <botan/scan_name.h> #include <string> #include <vector> @@ -24,8 +23,6 @@ namespace Botan { class BOTAN_DLL Cipher_Mode { public: - typedef SCAN_Name Spec; - virtual ~Cipher_Mode() {} /* diff --git a/src/lib/modes/ecb/ecb.cpp b/src/lib/modes/ecb/ecb.cpp index 650cfedf1..b39682fdf 100644 --- a/src/lib/modes/ecb/ecb.cpp +++ b/src/lib/modes/ecb/ecb.cpp @@ -5,8 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/mode_utils.h> #include <botan/ecb.h> +#include <botan/internal/rounding.h> namespace Botan { diff --git a/src/lib/modes/info.txt b/src/lib/modes/info.txt index 24508ecaa..1e50e7de5 100644 --- a/src/lib/modes/info.txt +++ b/src/lib/modes/info.txt @@ -4,7 +4,3 @@ define MODES 20150626 cipher_mode.h stream_mode.h </header:public> - -<header:internal> -mode_utils.h -</header:internal> diff --git a/src/lib/modes/mode_utils.h b/src/lib/modes/mode_utils.h deleted file mode 100644 index 3e4b7370b..000000000 --- a/src/lib/modes/mode_utils.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* 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/block_cipher.h> -#include <botan/loadstor.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 Cipher_Mode::Spec& spec) - { - if(std::unique_ptr<BlockCipher> bc = BlockCipher::create(spec.arg(0))) - return new T(bc.release()); - return nullptr; - } - -template<typename T, size_t LEN1> -T* make_block_cipher_mode_len(const Cipher_Mode::Spec& spec) - { - if(std::unique_ptr<BlockCipher> bc = BlockCipher::create(spec.arg(0))) - { - const size_t len1 = spec.arg_as_integer(1, LEN1); - return new T(bc.release(), len1); - } - - return nullptr; - } - -template<typename T, size_t LEN1, size_t LEN2> -T* make_block_cipher_mode_len2(const Cipher_Mode::Spec& spec) - { - if(std::unique_ptr<BlockCipher> bc = BlockCipher::create(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.release(), len1, len2); - } - - return nullptr; - } - -#define BOTAN_REGISTER_BLOCK_CIPHER_MODE(E, D) \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #E, E, make_block_cipher_mode<E>); \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #D, D, make_block_cipher_mode<D>) - -#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(E, D, LEN) \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #E, E, (make_block_cipher_mode_len<E, LEN>)); \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #D, D, (make_block_cipher_mode_len<D, LEN>)) - -#define BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN2(E, D, LEN1, LEN2) \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #E, E, (make_block_cipher_mode_len2<E, LEN1, LEN2>)); \ - BOTAN_REGISTER_NAMED_T(Cipher_Mode, #D, 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 1993bf15f..4b697ae6c 100644 --- a/src/lib/modes/xts/xts.cpp +++ b/src/lib/modes/xts/xts.cpp @@ -5,8 +5,8 @@ * 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> namespace Botan { diff --git a/src/lib/pbkdf/pbkdf.cpp b/src/lib/pbkdf/pbkdf.cpp index 01f52853a..a3485654b 100644 --- a/src/lib/pbkdf/pbkdf.cpp +++ b/src/lib/pbkdf/pbkdf.cpp @@ -6,7 +6,7 @@ */ #include <botan/pbkdf.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_PBKDF1) #include <botan/pbkdf1.h> @@ -18,28 +18,46 @@ namespace Botan { -#define BOTAN_REGISTER_PBKDF_1HASH(type, name) \ - BOTAN_REGISTER_NAMED_T(PBKDF, name, type, (make_new_T_1X<type, HashFunction>)) +PBKDF::~PBKDF() {} -#if defined(BOTAN_HAS_PBKDF1) -BOTAN_REGISTER_PBKDF_1HASH(PKCS5_PBKDF1, "PBKDF1"); -#endif +std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec, + const std::string& provider) + { + const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_PBKDF2) -BOTAN_REGISTER_NAMED_T(PBKDF, "PBKDF2", PKCS5_PBKDF2, PKCS5_PBKDF2::make); + if(req.algo_name() == "PBKDF2") + { + // TODO OpenSSL + + if(provider.empty() || provider == "base") + { + if(auto mac = MessageAuthenticationCode::create(req.arg(0))) + return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release())); + + if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")")) + return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release())); + } + + return nullptr; + } #endif -PBKDF::~PBKDF() {} +#if defined(BOTAN_HAS_PBKDF1) + if(req.algo_name() == "PBKDF1" && req.arg_count() == 1) + { + if(auto hash = HashFunction::create(req.arg(0))) + return std::unique_ptr<PBKDF>(new PKCS5_PBKDF1(hash.release())); -std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec, - const std::string& provider) - { - return std::unique_ptr<PBKDF>(make_a<PBKDF>(Botan::PBKDF::Spec(algo_spec), provider)); + } +#endif + + return nullptr; } std::vector<std::string> PBKDF::providers(const std::string& algo_spec) { - return providers_of<PBKDF>(PBKDF::Spec(algo_spec)); + return probe_providers_of<PBKDF>(algo_spec, { "base", "openssl" }); } void PBKDF::pbkdf_timed(byte out[], size_t out_len, diff --git a/src/lib/pbkdf/pbkdf.h b/src/lib/pbkdf/pbkdf.h index 63a8a82f0..3abac0896 100644 --- a/src/lib/pbkdf/pbkdf.h +++ b/src/lib/pbkdf/pbkdf.h @@ -9,8 +9,6 @@ #define BOTAN_PBKDF_H__ #include <botan/symkey.h> -#include <botan/scan_name.h> -#include <botan/scan_name.h> #include <botan/exceptn.h> #include <chrono> @@ -39,8 +37,6 @@ class BOTAN_DLL PBKDF */ static std::vector<std::string> providers(const std::string& algo_spec); - typedef SCAN_Name Spec; - /** * @return new instance of this same algorithm */ diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp index 5a8f529c6..0041fd537 100644 --- a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp +++ b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp @@ -11,17 +11,6 @@ namespace Botan { -PKCS5_PBKDF2* PKCS5_PBKDF2::make(const Spec& spec) - { - if(auto mac = MessageAuthenticationCode::create(spec.arg(0))) - return new PKCS5_PBKDF2(mac.release()); - - if(auto mac = MessageAuthenticationCode::create("HMAC(" + spec.arg(0) + ")")) - return new PKCS5_PBKDF2(mac.release()); - - return nullptr; - } - size_t pbkdf2(MessageAuthenticationCode& prf, byte out[], diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.h b/src/lib/pbkdf/pbkdf2/pbkdf2.h index 4f77f338b..36a3c640a 100644 --- a/src/lib/pbkdf/pbkdf2/pbkdf2.h +++ b/src/lib/pbkdf/pbkdf2/pbkdf2.h @@ -49,8 +49,6 @@ class BOTAN_DLL PKCS5_PBKDF2 final : public PBKDF * @param mac_fn the MAC object to use as PRF */ explicit PKCS5_PBKDF2(MessageAuthenticationCode* mac_fn) : m_mac(mac_fn) {} - - static PKCS5_PBKDF2* make(const Spec& spec); private: std::unique_ptr<MessageAuthenticationCode> m_mac; }; diff --git a/src/lib/pk_pad/eme.cpp b/src/lib/pk_pad/eme.cpp index b36ed6e67..eab9862af 100644 --- a/src/lib/pk_pad/eme.cpp +++ b/src/lib/pk_pad/eme.cpp @@ -6,7 +6,7 @@ */ #include <botan/eme.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_EME_OAEP) #include <botan/oaep.h> @@ -22,34 +22,34 @@ namespace Botan { -#define BOTAN_REGISTER_EME(name, maker) BOTAN_REGISTER_T(EME, name, maker) -#define BOTAN_REGISTER_EME_NOARGS(name) BOTAN_REGISTER_T_NOARGS(EME, name) - -#define BOTAN_REGISTER_EME_NAMED_NOARGS(type, name) \ - BOTAN_REGISTER_NAMED_T(EME, name, type, make_new_T<type>) - -#if defined(BOTAN_HAS_EME_OAEP) -BOTAN_REGISTER_NAMED_T(EME, "OAEP", OAEP, OAEP::make); +EME* get_eme(const std::string& algo_spec) + { +#if defined(BOTAN_HAS_EME_RAW) + if(algo_spec == "Raw") + return new EME_Raw; #endif #if defined(BOTAN_HAS_EME_PKCS1v15) -BOTAN_REGISTER_EME_NAMED_NOARGS(EME_PKCS1v15, "PKCS1v15"); + if(algo_spec == "PKCS1v15" || algo_spec == "EME-PKCS1-v1_5") + return new EME_PKCS1v15; #endif -#if defined(BOTAN_HAS_EME_RAW) -BOTAN_REGISTER_EME_NAMED_NOARGS(EME_Raw, "Raw"); +#if defined(BOTAN_HAS_EME_OAEP) + SCAN_Name req(algo_spec); + + if(req.algo_name() == "OAEP" || + req.algo_name() == "EME-OAEP" || + req.algo_name() == "EME1") + { + if(req.arg_count() == 1 || + (req.arg_count() == 2 && req.arg(1) == "MGF1")) + { + if(auto hash = HashFunction::create(req.arg(0))) + return new OAEP(hash.release()); + } + } #endif -EME* get_eme(const std::string& algo_spec) - { - SCAN_Name request(algo_spec); - - if(EME* eme = make_a<EME>(Botan::EME::Spec(algo_spec))) - return eme; - - if(request.algo_name() == "Raw") - return nullptr; // No padding - throw Algorithm_Not_Found(algo_spec); } diff --git a/src/lib/pk_pad/eme.h b/src/lib/pk_pad/eme.h index 9c72cb023..a5ad27b4e 100644 --- a/src/lib/pk_pad/eme.h +++ b/src/lib/pk_pad/eme.h @@ -8,7 +8,6 @@ #ifndef BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__ #define BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H__ -#include <botan/scan_name.h> #include <botan/secmem.h> #include <botan/rng.h> @@ -20,8 +19,6 @@ namespace Botan { class BOTAN_DLL EME { public: - typedef SCAN_Name Spec; - virtual ~EME() = default; /** diff --git a/src/lib/pk_pad/eme_oaep/oaep.cpp b/src/lib/pk_pad/eme_oaep/oaep.cpp index 1ae1068a7..81d41afea 100644 --- a/src/lib/pk_pad/eme_oaep/oaep.cpp +++ b/src/lib/pk_pad/eme_oaep/oaep.cpp @@ -11,21 +11,6 @@ namespace Botan { -OAEP* OAEP::make(const Spec& request) - { - if(request.algo_name() == "OAEP" && request.arg_count_between(1, 2)) - { - if(request.arg_count() == 1 || - (request.arg_count() == 2 && request.arg(1) == "MGF1")) - { - if(auto hash = HashFunction::create(request.arg(0))) - return new OAEP(hash.release()); - } - } - - return nullptr; - } - /* * OAEP Pad Operation */ diff --git a/src/lib/pk_pad/eme_oaep/oaep.h b/src/lib/pk_pad/eme_oaep/oaep.h index 2a0f0f28c..3e476f6a3 100644 --- a/src/lib/pk_pad/eme_oaep/oaep.h +++ b/src/lib/pk_pad/eme_oaep/oaep.h @@ -21,8 +21,6 @@ class BOTAN_DLL OAEP final : public EME public: size_t maximum_input_size(size_t) const override; - static OAEP* make(const Spec& spec); - /** * @param hash function to use for hashing (takes ownership) * @param P an optional label. Normally empty. diff --git a/src/lib/pk_pad/emsa.cpp b/src/lib/pk_pad/emsa.cpp index 4d4b96ad1..66e58fb0d 100644 --- a/src/lib/pk_pad/emsa.cpp +++ b/src/lib/pk_pad/emsa.cpp @@ -5,7 +5,7 @@ */ #include <botan/emsa.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_EMSA1) #include <botan/emsa1.h> @@ -33,10 +33,79 @@ EMSA::~EMSA() {} EMSA* get_emsa(const std::string& algo_spec) { - SCAN_Name request(algo_spec); + SCAN_Name req(algo_spec); - if(EMSA* emsa = make_a<EMSA>(Botan::EMSA::Spec(algo_spec))) - return emsa; +#if defined(BOTAN_HAS_EMSA1) + if(req.algo_name() == "EMSA1" && req.arg_count() == 1) + { + if(auto hash = HashFunction::create(req.arg(0))) + return new EMSA1(hash.release()); + } +#endif + +#if defined(BOTAN_HAS_EMSA_PKCS1) + if(req.algo_name() == "EMSA_PKCS1" || + req.algo_name() == "EMSA-PKCS1-v1_5" || + req.algo_name() == "EMSA3") + { + if(req.arg_count() == 1) + { + if(req.arg(0) == "Raw") + { + return new EMSA_PKCS1v15_Raw; + } + else + { + if(auto hash = HashFunction::create(req.arg(0))) + { + return new EMSA_PKCS1v15(hash.release()); + } + } + } + } +#endif + +#if defined(BOTAN_HAS_EMSA_PSSR) + if(req.algo_name() == "PSSR" || + req.algo_name() == "EMSA-PSS" || + req.algo_name() == "PSS-MGF1" || + req.algo_name() == "EMSA4") + { + if(req.arg_count_between(1, 3)) + { + if(req.arg(1, "MGF1") != "MGF1") + return nullptr; // not supported + + if(auto h = HashFunction::create(req.arg(0))) + { + const size_t salt_size = req.arg_as_integer(2, h->output_length()); + return new PSSR(h.release(), salt_size); + } + } + } +#endif + +#if defined(BOTAN_HAS_EMSA_X931) + if(req.algo_name() == "EMSA_X931" || + req.algo_name() == "EMSA2" || + req.algo_name() == "X9.31") + { + if(req.arg_count() == 1) + { + if(auto hash = HashFunction::create(req.arg(0))) + { + return new EMSA_X931(hash.release()); + } + } + } +#endif + +#if defined(BOTAN_HAS_EMSA_RAW) + if(req.algo_name() == "Raw" && req.arg_count() == 0) + { + return new EMSA_Raw; + } +#endif throw Algorithm_Not_Found(algo_spec); } @@ -54,35 +123,6 @@ std::string hash_for_emsa(const std::string& algo_spec) return "SHA-512"; // safe default if nothing we understand } -#define BOTAN_REGISTER_EMSA_NAMED_NOARGS(type, name) \ - BOTAN_REGISTER_NAMED_T(EMSA, name, type, make_new_T<type>) - -#define BOTAN_REGISTER_EMSA(name, maker) BOTAN_REGISTER_T(EMSA, name, maker) -#define BOTAN_REGISTER_EMSA_NOARGS(name) BOTAN_REGISTER_T_NOARGS(EMSA, name) - -#define BOTAN_REGISTER_EMSA_1HASH(type, name) \ - BOTAN_REGISTER_NAMED_T(EMSA, name, type, (make_new_T_1X<type, HashFunction>)) - -#if defined(BOTAN_HAS_EMSA1) -BOTAN_REGISTER_EMSA_1HASH(EMSA1, "EMSA1"); -#endif - -#if defined(BOTAN_HAS_EMSA_PKCS1) -BOTAN_REGISTER_NAMED_T(EMSA, "EMSA_PKCS1", EMSA_PCS1v15, EMSA_PKCS1v15::make); -#endif - -#if defined(BOTAN_HAS_EMSA_PSSR) -BOTAN_REGISTER_NAMED_T(EMSA, "PSSR", PSSR, PSSR::make); -#endif - -#if defined(BOTAN_HAS_EMSA_X931) -BOTAN_REGISTER_EMSA_1HASH(EMSA_X931, "EMSA_X931"); -#endif - -#if defined(BOTAN_HAS_EMSA_RAW) -BOTAN_REGISTER_EMSA_NAMED_NOARGS(EMSA_Raw, "Raw"); -#endif - } diff --git a/src/lib/pk_pad/emsa.h b/src/lib/pk_pad/emsa.h index 8e8720a66..bc930ae22 100644 --- a/src/lib/pk_pad/emsa.h +++ b/src/lib/pk_pad/emsa.h @@ -8,7 +8,6 @@ #ifndef BOTAN_PUBKEY_EMSA_H__ #define BOTAN_PUBKEY_EMSA_H__ -#include <botan/scan_name.h> #include <botan/secmem.h> #include <botan/rng.h> @@ -22,8 +21,6 @@ namespace Botan { class BOTAN_DLL EMSA { public: - typedef SCAN_Name Spec; - /** * Add more data to the signature computation * @param input some data diff --git a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp index e990ef8af..b3f74930b 100644 --- a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp +++ b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp @@ -10,18 +10,6 @@ namespace Botan { -EMSA* EMSA_PKCS1v15::make(const EMSA::Spec& spec) - { - if(spec.arg(0) == "Raw") - return new EMSA_PKCS1v15_Raw; - else - { - if(auto h = HashFunction::create(spec.arg(0))) - return new EMSA_PKCS1v15(h.release()); - } - return nullptr; - } - namespace { secure_vector<byte> emsa3_encoding(const secure_vector<byte>& msg, diff --git a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h index 917f03ac8..65daaf7ce 100644 --- a/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h +++ b/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h @@ -21,8 +21,6 @@ namespace Botan { class BOTAN_DLL EMSA_PKCS1v15 final : public EMSA { public: - static EMSA* make(const EMSA::Spec& spec); - /** * @param hash the hash function to use */ diff --git a/src/lib/pk_pad/emsa_pssr/pssr.cpp b/src/lib/pk_pad/emsa_pssr/pssr.cpp index ddd8c5f0b..a41e79e78 100644 --- a/src/lib/pk_pad/emsa_pssr/pssr.cpp +++ b/src/lib/pk_pad/emsa_pssr/pssr.cpp @@ -11,20 +11,6 @@ namespace Botan { -PSSR* PSSR::make(const Spec& request) - { - if(request.arg(1, "MGF1") != "MGF1") - return nullptr; - - if(auto h = HashFunction::create(request.arg(0))) - { - const size_t salt_size = request.arg_as_integer(2, h->output_length()); - return new PSSR(h.release(), salt_size); - } - - return nullptr; - } - /* * PSSR Update Operation */ diff --git a/src/lib/pk_pad/emsa_pssr/pssr.h b/src/lib/pk_pad/emsa_pssr/pssr.h index fa8687fee..bf465eadf 100644 --- a/src/lib/pk_pad/emsa_pssr/pssr.h +++ b/src/lib/pk_pad/emsa_pssr/pssr.h @@ -32,8 +32,6 @@ class BOTAN_DLL PSSR final : public EMSA PSSR(HashFunction* hash, size_t salt_size); EMSA* clone() override { return new PSSR(m_hash->clone(), m_SALT_SIZE); } - - static PSSR* make(const Spec& spec); private: void update(const byte input[], size_t length) override; diff --git a/src/lib/prov/openssl/openssl.h b/src/lib/prov/openssl/openssl.h index 58a7d77dc..8b2b41c1d 100644 --- a/src/lib/prov/openssl/openssl.h +++ b/src/lib/prov/openssl/openssl.h @@ -1,12 +1,12 @@ /* * Utils for calling OpenSSL -* (C) 2015 Jack Lloyd +* (C) 2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ -#ifndef BOTAN_OPENSSL_H__ -#define BOTAN_OPENSSL_H__ +#ifndef BOTAN_INTERNAL_OPENSSL_H__ +#define BOTAN_INTERNAL_OPENSSL_H__ #include <botan/internal/pk_ops.h> #include <botan/secmem.h> @@ -15,9 +15,18 @@ #include <string> #include <openssl/err.h> +#include <openssl/evp.h> + +#if defined(BOTAN_HAS_RC4) +#include <openssl/rc4.h> +#endif namespace Botan { +class BlockCipher; +class StreamCipher; +class HashFunction; + class OpenSSL_Error : public Exception { public: @@ -25,9 +34,15 @@ class OpenSSL_Error : public Exception Exception(what + " failed: " + ERR_error_string(ERR_get_error(), nullptr)) {} }; -#define BOTAN_OPENSSL_BLOCK_PRIO 150 -#define BOTAN_OPENSSL_HASH_PRIO 150 -#define BOTAN_OPENSSL_RC4_PRIO 150 +/* Block Ciphers */ + +std::unique_ptr<BlockCipher> +make_openssl_block_cipher(const std::string& name); + +/* Hash */ + +std::unique_ptr<HashFunction> +make_openssl_hash(const std::string& name); /* RSA */ @@ -73,6 +88,12 @@ make_openssl_ecdh_ka_op(const ECDH_PrivateKey& key, const std::string& params); #endif +#if defined(BOTAN_HAS_RC4) + +std::unique_ptr<StreamCipher> +make_openssl_rc4(size_t skip); + +#endif } diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp index 8f5ae89b1..cb98be70d 100644 --- a/src/lib/prov/openssl/openssl_block.cpp +++ b/src/lib/prov/openssl/openssl_block.cpp @@ -6,7 +6,6 @@ */ #include <botan/block_cipher.h> -#include <botan/internal/algo_registry.h> #include <botan/internal/openssl.h> #include <openssl/evp.h> @@ -17,10 +16,12 @@ namespace { class OpenSSL_BlockCipher : public BlockCipher { public: - OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&); + OpenSSL_BlockCipher(const std::string& name, + const EVP_CIPHER* cipher); - OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&, - size_t, size_t, size_t); + OpenSSL_BlockCipher(const std::string& name, + const EVP_CIPHER* cipher, + size_t kl_min, size_t kl_max, size_t kl_mod); ~OpenSSL_BlockCipher(); @@ -53,8 +54,8 @@ class OpenSSL_BlockCipher : public BlockCipher mutable EVP_CIPHER_CTX m_encrypt, m_decrypt; }; -OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name) : +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name, + const EVP_CIPHER* algo) : m_block_sz(EVP_CIPHER_block_size(algo)), m_cipher_key_spec(EVP_CIPHER_key_length(algo)), m_cipher_name(algo_name) @@ -72,10 +73,11 @@ OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, EVP_CIPHER_CTX_set_padding(&m_decrypt, 0); } -OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name, - size_t key_min, size_t key_max, - size_t key_mod) : +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name, + const EVP_CIPHER* algo, + size_t key_min, + size_t key_max, + size_t key_mod) : m_block_sz(EVP_CIPHER_block_size(algo)), m_cipher_key_spec(key_min, key_max, key_mod), m_cipher_name(algo_name) @@ -125,11 +127,11 @@ void OpenSSL_BlockCipher::key_schedule(const byte key[], size_t length) */ BlockCipher* OpenSSL_BlockCipher::clone() const { - return new OpenSSL_BlockCipher(EVP_CIPHER_CTX_cipher(&m_encrypt), - m_cipher_name, - m_cipher_key_spec.minimum_keylength(), - m_cipher_key_spec.maximum_keylength(), - m_cipher_key_spec.keylength_multiple()); + return new OpenSSL_BlockCipher(m_cipher_name, + EVP_CIPHER_CTX_cipher(&m_encrypt), + m_cipher_key_spec.minimum_keylength(), + m_cipher_key_spec.maximum_keylength(), + m_cipher_key_spec.keylength_multiple()); } /* @@ -149,67 +151,63 @@ void OpenSSL_BlockCipher::clear() EVP_CIPHER_CTX_set_padding(&m_decrypt, 0); } -std::function<BlockCipher* (const BlockCipher::Spec&)> -make_evp_block_maker(const EVP_CIPHER* cipher, const char* algo) - { - return [cipher,algo](const BlockCipher::Spec&) - { - return new OpenSSL_BlockCipher(cipher, algo); - }; - } +} -std::function<BlockCipher* (const BlockCipher::Spec&)> -make_evp_block_maker_keylen(const EVP_CIPHER* cipher, const char* algo, - size_t kmin, size_t kmax, size_t kmod) +std::unique_ptr<BlockCipher> +make_openssl_block_cipher(const std::string& name) { - return [cipher,algo,kmin,kmax,kmod](const BlockCipher::Spec&) - { - return new OpenSSL_BlockCipher(cipher, algo, kmin, kmax, kmod); - }; - } - -#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK(NAME, EVP) \ - BOTAN_REGISTER_TYPE(BlockCipher, EVP_BlockCipher ## EVP, NAME, \ - make_evp_block_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_BLOCK_PRIO) - -#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN(NAME, EVP, KMIN, KMAX, KMOD) \ - BOTAN_REGISTER_TYPE(BlockCipher, OpenSSL_BlockCipher ## EVP, NAME, \ - make_evp_block_maker_keylen(EVP(), NAME, KMIN, KMAX, KMOD), \ - "openssl", BOTAN_OPENSSL_BLOCK_PRIO) - -#if !defined(OPENSSL_NO_AES) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-128", EVP_aes_128_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-192", EVP_aes_192_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-256", EVP_aes_256_ecb); +#define MAKE_OPENSSL_BLOCK(evp_fn) \ + std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn())) +#define MAKE_OPENSSL_BLOCK_KEYLEN(evp_fn, kl_min, kl_max, kl_mod) \ + std::unique_ptr<BlockCipher>(new OpenSSL_BlockCipher(name, evp_fn(), kl_min, kl_max, kl_mod)) + +#if defined(BOTAN_HAS_AES) && !defined(OPENSSL_NO_AES) + if(name == "AES-128") + return MAKE_OPENSSL_BLOCK(EVP_aes_128_ecb); + if(name == "AES-192") + return MAKE_OPENSSL_BLOCK(EVP_aes_192_ecb); + if(name == "AES-256") + return MAKE_OPENSSL_BLOCK(EVP_aes_256_ecb); #endif -#if !defined(OPENSSL_NO_DES) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("DES", EVP_des_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("TripleDES", EVP_des_ede3_ecb, 16, 24, 8); +#if defined(BOTAN_HAS_CAMELLIA) && !defined(OPENSSL_NO_CAMELLIA) + if(name == "Camellia-128") + return MAKE_OPENSSL_BLOCK(EVP_camellia_128_ecb); + if(name == "Camellia-192") + return MAKE_OPENSSL_BLOCK(EVP_camellia_192_ecb); + if(name == "Camellia-256") + return MAKE_OPENSSL_BLOCK(EVP_camellia_256_ecb); #endif -#if !defined(OPENSSL_NO_BF) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("Blowfish", EVP_bf_ecb, 1, 56, 1); +#if defined(BOTAN_HAS_DES) && !defined(OPENSSL_NO_DES) + if(name == "DES") + return MAKE_OPENSSL_BLOCK(EVP_des_ecb); + if(name == "TripleDES") + return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_des_ede3_ecb, 16, 24, 8); #endif -#if !defined(OPENSSL_NO_CAST) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("CAST-128", EVP_cast5_ecb, 1, 16, 1); +#if defined(BOTAN_HAS_BLOWFISH) && !defined(OPENSSL_NO_BF) + if(name == "Blowfish") + return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_bf_ecb, 1, 56, 1); #endif -#if !defined(OPENSSL_NO_CAMELLIA) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-128", EVP_camellia_128_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-192", EVP_camellia_192_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-256", EVP_camellia_256_ecb); +#if defined(BOTAN_HAS_CAST) && !defined(OPENSSL_NO_CAST) + if(name == "CAST-128") + return MAKE_OPENSSL_BLOCK_KEYLEN(EVP_cast5_ecb, 1, 16, 1); #endif -#if !defined(OPENSSL_NO_IDEA) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("IDEA", EVP_idea_ecb); +#if defined(BOTAN_HAS_IDEA) && !defined(OPENSSL_NO_IDEA) + if(name == "IDEA") + return MAKE_OPENSSL_BLOCK(EVP_idea_ecb); #endif -#if !defined(OPENSSL_NO_SEED) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("SEED", EVP_seed_ecb); +#if defined(BOTAN_HAS_SEED) && !defined(OPENSSL_NO_SEED) + if(name == "SEED") + return MAKE_OPENSSL_BLOCK(EVP_seed_ecb); #endif -} + return nullptr; + } } + diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp index aee31ce71..7b20b1c73 100644 --- a/src/lib/prov/openssl/openssl_ec.cpp +++ b/src/lib/prov/openssl/openssl_ec.cpp @@ -67,19 +67,20 @@ int OpenSSL_EC_nid_for(const OID& oid) if(oid.empty()) return -1; - static const std::map<std::string, int> nid_map = { - { "secp192r1", NID_X9_62_prime192v1 }, - { "secp224r1", NID_secp224r1 }, - { "secp256r1", NID_X9_62_prime256v1 }, - { "secp384r1", NID_secp384r1 }, - { "secp521r1", NID_secp521r1 }, - // TODO: OpenSSL 1.0.2 added brainpool curves - }; - const std::string name = OIDS::lookup(oid); - auto i = nid_map.find(name); - if(i != nid_map.end()) - return i->second; + + if(name == "secp192r1") + return NID_X9_62_prime192v1; + if(name == "secp224r1") + return NID_secp224r1; + if(name == "secp256r1") + return NID_X9_62_prime256v1; + if(name == "secp384r1") + return NID_secp384r1; + if(name == "secp521r1") + return NID_secp521r1; + + // TODO: OpenSSL 1.0.2 added brainpool curves return -1; } diff --git a/src/lib/prov/openssl/openssl_hash.cpp b/src/lib/prov/openssl/openssl_hash.cpp index 15aebeb94..8e36866a1 100644 --- a/src/lib/prov/openssl/openssl_hash.cpp +++ b/src/lib/prov/openssl/openssl_hash.cpp @@ -7,8 +7,8 @@ #include <botan/hash.h> #include <botan/internal/openssl.h> -#include <botan/internal/algo_registry.h> #include <openssl/evp.h> +#include <unordered_map> namespace Botan { @@ -29,7 +29,7 @@ class OpenSSL_HashFunction : public HashFunction HashFunction* clone() const override { const EVP_MD* algo = EVP_MD_CTX_md(&m_md); - return new OpenSSL_HashFunction(algo, name()); + return new OpenSSL_HashFunction(name(), algo); } size_t output_length() const override @@ -42,7 +42,7 @@ class OpenSSL_HashFunction : public HashFunction return EVP_MD_block_size(EVP_MD_CTX_md(&m_md)); } - OpenSSL_HashFunction(const EVP_MD* md, const std::string& name) : m_name(name) + OpenSSL_HashFunction(const std::string& name, const EVP_MD* md) : m_name(name) { EVP_MD_CTX_init(&m_md); EVP_DigestInit_ex(&m_md, md, nullptr); @@ -70,45 +70,49 @@ class OpenSSL_HashFunction : public HashFunction EVP_MD_CTX m_md; }; -std::function<HashFunction* (const HashFunction::Spec&)> -make_evp_hash_maker(const EVP_MD* md, const char* algo) - { - return [md,algo](const HashFunction::Spec&) - { - return new OpenSSL_HashFunction(md, algo); - }; - } - -#define BOTAN_REGISTER_OPENSSL_EVP_HASH(NAME, EVP) \ - BOTAN_REGISTER_TYPE(HashFunction, OpenSSL_HashFunction ## EVP, NAME, \ - make_evp_hash_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_HASH_PRIO) +} -#if !defined(OPENSSL_NO_SHA) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-160", EVP_sha1); +std::unique_ptr<HashFunction> +make_openssl_hash(const std::string& name) + { +#define MAKE_OPENSSL_HASH(fn) \ + std::unique_ptr<HashFunction>(new OpenSSL_HashFunction(name, fn ())) + +#if defined(BOTAN_HAS_SHA2_32) && !defined(OPENSSL_NO_SHA256) + if(name == "SHA-224") + return MAKE_OPENSSL_HASH(EVP_sha224); + if(name == "SHA-256") + return MAKE_OPENSSL_HASH(EVP_sha256); #endif -#if !defined(OPENSSL_NO_SHA256) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-224", EVP_sha224); - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-256", EVP_sha256); +#if defined(BOTAN_HAS_SHA2_64) && !defined(OPENSSL_NO_SHA512) + if(name == "SHA-384") + return MAKE_OPENSSL_HASH(EVP_sha384); + if(name == "SHA-512") + return MAKE_OPENSSL_HASH(EVP_sha512); #endif -#if !defined(OPENSSL_NO_SHA512) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-384", EVP_sha384); - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-512", EVP_sha512); +#if defined(BOTAN_HAS_SHA1) && !defined(OPENSSL_NO_SHA) + if(name == "SHA-160") + return MAKE_OPENSSL_HASH(EVP_sha1); #endif -#if !defined(OPENSSL_NO_MD4) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD4", EVP_md4); +#if defined(BOTAN_HAS_RIPEMD_160) && !defined(OPENSSL_NO_RIPEMD) + if(name == "RIPEMD-160") + return MAKE_OPENSSL_HASH(EVP_ripemd160); #endif -#if !defined(OPENSSL_NO_MD5) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD5", EVP_md5); -#endif +#if defined(BOTAN_HAS_MD5) && !defined(OPENSSL_NO_MD5) + if(name == "MD5") + return MAKE_OPENSSL_HASH(EVP_md5); + #endif -#if !defined(OPENSSL_NO_RIPEMD) - BOTAN_REGISTER_OPENSSL_EVP_HASH("RIPEMD-160", EVP_ripemd160); +#if defined(BOTAN_HAS_MD4) && !defined(OPENSSL_NO_MD4) + if(name == "MD4") + return MAKE_OPENSSL_HASH(EVP_md4); #endif -} + return nullptr; + } } diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp index 3db62c32a..b43d801ed 100644 --- a/src/lib/prov/openssl/openssl_rc4.cpp +++ b/src/lib/prov/openssl/openssl_rc4.cpp @@ -9,7 +9,6 @@ #if defined(BOTAN_HAS_OPENSSL) && defined(BOTAN_HAS_RC4) -#include <botan/internal/algo_registry.h> #include <botan/internal/openssl.h> #include <botan/parsing.h> #include <botan/exceptn.h> @@ -49,9 +48,10 @@ class OpenSSL_RC4 : public StreamCipher explicit OpenSSL_RC4(size_t skip = 0) : m_skip(skip) { clear(); } ~OpenSSL_RC4() { clear(); } - void set_iv(const byte*, size_t) override + void set_iv(const byte*, size_t len) override { - throw Exception("RC4 does not support an IV"); + if(len > 0) + throw Exception("RC4 does not support an IV"); } void seek(u64bit) override @@ -78,8 +78,12 @@ class OpenSSL_RC4 : public StreamCipher } -BOTAN_REGISTER_TYPE(StreamCipher, OpenSSL_RC4, "RC4", (make_new_T_1len<OpenSSL_RC4,0>), - "openssl", BOTAN_OPENSSL_RC4_PRIO); +std::unique_ptr<StreamCipher> +make_openssl_rc4(size_t skip) + { + return std::unique_ptr<StreamCipher>(new OpenSSL_RC4(skip)); + } + } diff --git a/src/lib/prov/pkcs11/p11_ecdh.cpp b/src/lib/prov/pkcs11/p11_ecdh.cpp index 6f88f43d6..474d1dac0 100644 --- a/src/lib/prov/pkcs11/p11_ecdh.cpp +++ b/src/lib/prov/pkcs11/p11_ecdh.cpp @@ -13,7 +13,6 @@ #include <botan/internal/p11_mechanism.h> #include <botan/ber_dec.h> #include <botan/der_enc.h> -#include <botan/internal/algo_registry.h> #include <botan/internal/pk_ops.h> #include <botan/rng.h> diff --git a/src/lib/prov/pkcs11/p11_ecdsa.cpp b/src/lib/prov/pkcs11/p11_ecdsa.cpp index 076bb2498..dede8bd6c 100644 --- a/src/lib/prov/pkcs11/p11_ecdsa.cpp +++ b/src/lib/prov/pkcs11/p11_ecdsa.cpp @@ -11,7 +11,6 @@ #if defined(BOTAN_HAS_ECDSA) #include <botan/internal/p11_mechanism.h> -#include <botan/internal/algo_registry.h> #include <botan/internal/pk_ops.h> #include <botan/keypair.h> #include <botan/rng.h> diff --git a/src/lib/prov/pkcs11/p11_rsa.cpp b/src/lib/prov/pkcs11/p11_rsa.cpp index c23c8f5f3..9c0f75157 100644 --- a/src/lib/prov/pkcs11/p11_rsa.cpp +++ b/src/lib/prov/pkcs11/p11_rsa.cpp @@ -12,7 +12,6 @@ #include <botan/internal/p11_mechanism.h> #include <botan/internal/pk_ops.h> -#include <botan/internal/algo_registry.h> #include <botan/internal/pk_ops.h> #include <botan/rng.h> #include <botan/blinding.h> diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index 43609ba2d..c4552d459 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -9,16 +9,6 @@ namespace Botan { -CTR_BE* CTR_BE::make(const Spec& spec) - { - if(spec.algo_name() == "CTR-BE" && spec.arg_count() == 1) - { - if(auto c = BlockCipher::create(spec.arg(0))) - return new CTR_BE(c.release()); - } - return nullptr; - } - CTR_BE::CTR_BE(BlockCipher* ciph) : m_cipher(ciph), m_counter(m_cipher->parallel_bytes()), diff --git a/src/lib/stream/ctr/ctr.h b/src/lib/stream/ctr/ctr.h index 385edac54..c4a28bd2b 100644 --- a/src/lib/stream/ctr/ctr.h +++ b/src/lib/stream/ctr/ctr.h @@ -38,8 +38,6 @@ class BOTAN_DLL CTR_BE final : public StreamCipher void clear() override; - static CTR_BE* make(const Spec& spec); - /** * @param cipher the block cipher to use */ diff --git a/src/lib/stream/ofb/ofb.cpp b/src/lib/stream/ofb/ofb.cpp index 3337a0c14..0c23188d5 100644 --- a/src/lib/stream/ofb/ofb.cpp +++ b/src/lib/stream/ofb/ofb.cpp @@ -9,16 +9,6 @@ namespace Botan { -OFB* OFB::make(const Spec& spec) - { - if(spec.algo_name() == "OFB" && spec.arg_count() == 1) - { - if(auto c = BlockCipher::create(spec.arg(0))) - return new OFB(c.release()); - } - return nullptr; - } - OFB::OFB(BlockCipher* cipher) : m_cipher(cipher), m_buffer(m_cipher->block_size()), diff --git a/src/lib/stream/ofb/ofb.h b/src/lib/stream/ofb/ofb.h index 7d77bae7a..f8beb4956 100644 --- a/src/lib/stream/ofb/ofb.h +++ b/src/lib/stream/ofb/ofb.h @@ -38,8 +38,6 @@ class BOTAN_DLL OFB final : public StreamCipher void clear() override; - static OFB* make(const Spec& spec); - /** * @param cipher the block cipher to use */ diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp index e5ea2e2b8..47dc1ce29 100644 --- a/src/lib/stream/rc4/rc4.cpp +++ b/src/lib/stream/rc4/rc4.cpp @@ -10,15 +10,6 @@ namespace Botan { -RC4* RC4::make(const Spec& spec) - { - if(spec.algo_name() == "RC4") - return new RC4(spec.arg_as_integer(0, 0)); - if(spec.algo_name() == "RC4_drop") - return new RC4(768); - return nullptr; - } - /* * Combine cipher stream with message */ @@ -36,9 +27,10 @@ void RC4::cipher(const byte in[], byte out[], size_t length) m_position += length; } -void RC4::set_iv(const byte*, size_t) +void RC4::set_iv(const byte*, size_t length) { - throw Exception("RC4 does not support an IV"); + if(length > 0) + throw Exception("RC4 does not support an IV"); } /* diff --git a/src/lib/stream/rc4/rc4.h b/src/lib/stream/rc4/rc4.h index 82dd6097b..46715f7d2 100644 --- a/src/lib/stream/rc4/rc4.h +++ b/src/lib/stream/rc4/rc4.h @@ -33,8 +33,6 @@ class BOTAN_DLL RC4 final : public StreamCipher return Key_Length_Specification(1, 256); } - static RC4* make(const Spec& spec); - /** * @param skip skip this many initial bytes in the keystream */ diff --git a/src/lib/stream/stream_cipher.cpp b/src/lib/stream/stream_cipher.cpp index 7c41722a0..4b27caafe 100644 --- a/src/lib/stream/stream_cipher.cpp +++ b/src/lib/stream/stream_cipher.cpp @@ -1,12 +1,12 @@ /* * Stream Ciphers -* (C) 2015 Jack Lloyd +* (C) 2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/stream_cipher.h> -#include <botan/internal/algo_registry.h> +#include <botan/scan_name.h> #if defined(BOTAN_HAS_CHACHA) #include <botan/chacha.h> @@ -32,44 +32,104 @@ #include <botan/rc4.h> #endif +#if defined(BOTAN_HAS_OPENSSL) + #include <botan/internal/openssl.h> +#endif + namespace Botan { std::unique_ptr<StreamCipher> StreamCipher::create(const std::string& algo_spec, const std::string& provider) { - return std::unique_ptr<StreamCipher>(make_a<StreamCipher>(Botan::StreamCipher::Spec(algo_spec), provider)); - } - -std::vector<std::string> StreamCipher::providers(const std::string& algo_spec) - { - return providers_of<StreamCipher>(StreamCipher::Spec(algo_spec)); - } + const SCAN_Name req(algo_spec); -StreamCipher::StreamCipher() {} -StreamCipher::~StreamCipher() {} +#if defined(BOTAN_HAS_CTR_BE) + if(req.algo_name() == "CTR-BE" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto c = BlockCipher::create(req.arg(0))) + return std::unique_ptr<StreamCipher>(new CTR_BE(c.release())); + } + } +#endif #if defined(BOTAN_HAS_CHACHA) -BOTAN_REGISTER_T_1LEN(StreamCipher, ChaCha, 20); + if(req.algo_name() == "ChaCha") + { + if(provider.empty() || provider == "base") + return std::unique_ptr<StreamCipher>(new ChaCha(req.arg_as_integer(0, 20))); + } #endif #if defined(BOTAN_HAS_SALSA20) -BOTAN_REGISTER_T_NOARGS(StreamCipher, Salsa20); + if(req.algo_name() == "Salsa20") + { + if(provider.empty() || provider == "base") + return std::unique_ptr<StreamCipher>(new Salsa20); + } #endif #if defined(BOTAN_HAS_SHAKE_CIPHER) -BOTAN_REGISTER_NAMED_T(StreamCipher, "SHAKE-128", SHAKE_128, make_new_T<SHAKE_128>); -#endif - -#if defined(BOTAN_HAS_CTR_BE) -BOTAN_REGISTER_NAMED_T(StreamCipher, "CTR-BE", CTR_BE, CTR_BE::make); + if(req.algo_name() == "SHAKE-128") + { + if(provider.empty() || provider == "base") + return std::unique_ptr<StreamCipher>(new SHAKE_128); + } #endif #if defined(BOTAN_HAS_OFB) -BOTAN_REGISTER_NAMED_T(StreamCipher, "OFB", OFB, OFB::make); + if(req.algo_name() == "OFB" && req.arg_count() == 1) + { + if(provider.empty() || provider == "base") + { + if(auto c = BlockCipher::create(req.arg(0))) + return std::unique_ptr<StreamCipher>(new OFB(c.release())); + } + } #endif #if defined(BOTAN_HAS_RC4) -BOTAN_REGISTER_NAMED_T(StreamCipher, "RC4", RC4, RC4::make); + + if(req.algo_name() == "RC4" || + req.algo_name() == "ARC4" || + req.algo_name() == "MARK-4") + { + const size_t skip = (req.algo_name() == "MARK-4") ? 256 : req.arg_as_integer(0, 0); + +#if defined(BOTAN_HAS_OPENSSL) + if(provider.empty() || provider == "openssl") + { + return std::unique_ptr<StreamCipher>(make_openssl_rc4(skip)); + } #endif + if(provider.empty() || provider == "base") + { + return std::unique_ptr<StreamCipher>(new RC4(skip)); + } + } + +#endif + + return nullptr; + } + +//static +std::unique_ptr<StreamCipher> +StreamCipher::create_or_throw(const std::string& algo, + const std::string& provider) + { + if(auto sc = StreamCipher::create(algo, provider)) + { + return sc; + } + throw Lookup_Error("Stream cipher", algo, provider); + } + +std::vector<std::string> StreamCipher::providers(const std::string& algo_spec) + { + return probe_providers_of<StreamCipher>(algo_spec, {"base", "openssl"}); + } + } diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h index 0cbdf3c65..7654bf427 100644 --- a/src/lib/stream/stream_cipher.h +++ b/src/lib/stream/stream_cipher.h @@ -9,7 +9,7 @@ #define BOTAN_STREAM_CIPHER_H__ #include <botan/sym_algo.h> -#include <botan/scan_name.h> +#include <string> namespace Botan { @@ -19,7 +19,7 @@ namespace Botan { class BOTAN_DLL StreamCipher : public SymmetricAlgorithm { public: - typedef SCAN_Name Spec; + virtual ~StreamCipher() {} /** * Create an instance based on a name @@ -28,8 +28,20 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm * @param provider provider implementation to use * @return a null pointer if the algo/provider combination cannot be found */ - static std::unique_ptr<StreamCipher> create(const std::string& algo_spec, - const std::string& provider = ""); + static std::unique_ptr<StreamCipher> + create(const std::string& algo_spec, + const std::string& provider = ""); + + /** + * Create an instance based on a name + * If provider is empty then best available is chosen. + * @param algo_spec algorithm name + * @param provider provider implementation to use + * Throws a Lookup_Error if the algo/provider combination cannot be found + */ + static std::unique_ptr<StreamCipher> + create_or_throw(const std::string& algo_spec, + const std::string& provider = ""); /** * @return list of available providers for this algorithm, empty if not available @@ -109,9 +121,6 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm * might also return "sse2", "avx2", "openssl", or some other arbitrary string. */ virtual std::string provider() const { return "base"; } - - StreamCipher(); - virtual ~StreamCipher(); }; } diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h index bfde49002..798f2240a 100644 --- a/src/lib/utils/exceptn.h +++ b/src/lib/utils/exceptn.h @@ -73,6 +73,13 @@ struct BOTAN_DLL Lookup_Error : public Exception explicit Lookup_Error(const std::string& err) : Exception(err) {} + + Lookup_Error(const std::string& type, + const std::string& algo, + const std::string& provider) : + Exception("Unavailable " + type + " " + algo + + (provider.empty() ? std::string("") : (" for provider " + provider))) + {} }; /** diff --git a/src/tests/test_ecies.cpp b/src/tests/test_ecies.cpp index dc9347b6e..f65b015a5 100644 --- a/src/tests/test_ecies.cpp +++ b/src/tests/test_ecies.cpp @@ -101,7 +101,7 @@ void check_encrypt_decrypt(Test::Result& result, const Botan::ECDH_PrivateKey& p plaintext, std::vector<byte>()); } -#if defined(BOTAN_HAS_KDF1_18033) +#if defined(BOTAN_HAS_KDF1_18033) && defined(BOTAN_HAS_SHA1) class ECIES_ISO_Tests : public Text_Based_Test { diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp index aca9d7ef6..dc93bb4d1 100644 --- a/src/tests/test_hash.cpp +++ b/src/tests/test_hash.cpp @@ -8,10 +8,6 @@ #include <botan/hash.h> -#if defined (BOTAN_HAS_PARALLEL_HASH) - #include <botan/par_hash.h> -#endif - namespace Botan_Tests { namespace { @@ -46,14 +42,19 @@ class Hash_Function_Tests : public Text_Based_Test continue; } + std::unique_ptr<Botan::HashFunction> clone(hash->clone()); + const std::string provider(hash->provider()); result.test_is_nonempty("provider", provider); result.test_eq(provider, hash->name(), algo); + result.test_eq(provider, hash->name(), clone->name()); hash->update(input); - result.test_eq(provider, "hashing", hash->final(), expected); + clone->update(input); + result.test_eq(provider, "hashing (clone)", clone->final(), expected); + // Test to make sure clear() resets what we need it to hash->update("some discarded input"); hash->clear(); @@ -77,97 +78,6 @@ class Hash_Function_Tests : public Text_Based_Test BOTAN_REGISTER_TEST("hash", Hash_Function_Tests); -#if defined(BOTAN_HAS_PARALLEL_HASH) - -Test::Result test_clone() - { - Test::Result result("Parallel hash"); - - std::string algo = "Parallel(MD5,SHA-160)"; - std::unique_ptr<Botan::HashFunction> hash(Botan::HashFunction::create(algo)); - - if(!hash) - { - result.note_missing(algo); - return result; - } - - hash->update(""); - result.test_eq("Parallel hashing", hash->final(), "D41D8CD98F00B204E9800998ECF8427EDA39A3EE5E" - "6B4B0D3255BFEF95601890AFD80709"); - - std::unique_ptr<Botan::HashFunction> hash_clone(hash->clone()); - - hash_clone->clear(); - hash_clone->update(""); - result.test_eq("Parallel hashing (clone)", hash_clone->final(), "D41D8CD98F00B204E9800998ECF8427" - "EDA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); - - return result; - } - -Test::Result test_ctor() - { - Test::Result result("Parallel hash"); - - std::unique_ptr<Botan::HashFunction> sha256(Botan::HashFunction::create("SHA-256")); - if(!sha256) - { - result.note_missing("SHA-256"); - return result; - } - - std::unique_ptr<Botan::HashFunction> sha512(Botan::HashFunction::create("SHA-512")); - if(!sha512) - { - result.note_missing("SHA-512"); - return result; - } - - std::vector<Botan::HashFunction*> hashes = { sha256.get(), sha512.get() }; - Botan::Parallel par_hash(hashes); - - par_hash.update(""); - result.test_eq("Parallel hashing", par_hash.final(), "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B" - "934CA495991B7852B855CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9C" - "E47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E"); - - return result; - } - -class Parallel_Hash_Tests : public Test - { - public: - std::vector<Test::Result> run() override - { - std::vector<Test::Result> results; - - std::vector<std::function<Test::Result()>> fns = - { - test_clone, - test_ctor - }; - - for(size_t i = 0; i != fns.size(); ++i) - { - try - { - results.push_back(fns[ i ]()); - } - catch(std::exception& e) - { - results.push_back(Test::Result::Failure("Parallel hash tests " + std::to_string(i), e.what())); - } - } - - return results; - } - }; - -BOTAN_REGISTER_TEST("par_hash", Parallel_Hash_Tests); - -#endif - } } |