diff options
Diffstat (limited to 'src/lib/algo_base')
-rw-r--r-- | src/lib/algo_base/algo_registry.cpp | 20 | ||||
-rw-r--r-- | src/lib/algo_base/algo_registry.h | 146 | ||||
-rw-r--r-- | src/lib/algo_base/scan_name.cpp | 16 | ||||
-rw-r--r-- | src/lib/algo_base/scan_name.h | 16 | ||||
-rw-r--r-- | src/lib/algo_base/transform.h | 19 |
5 files changed, 201 insertions, 16 deletions
diff --git a/src/lib/algo_base/algo_registry.cpp b/src/lib/algo_base/algo_registry.cpp new file mode 100644 index 000000000..c33b1b3c7 --- /dev/null +++ b/src/lib/algo_base/algo_registry.cpp @@ -0,0 +1,20 @@ +/* +* (C) 2014,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/transform.h> +#include <botan/algo_registry.h> + +namespace Botan { + +Transform* get_transform(const std::string& specstr, + const std::string& provider, + const std::string& dirstr) + { + Algo_Registry<Transform>::Spec spec(specstr, dirstr); + return Algo_Registry<Transform>::global_registry().make(spec, provider); + } + +} diff --git a/src/lib/algo_base/algo_registry.h b/src/lib/algo_base/algo_registry.h new file mode 100644 index 000000000..d40e9fc67 --- /dev/null +++ b/src/lib/algo_base/algo_registry.h @@ -0,0 +1,146 @@ +/* +* (C) 2014,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ALGO_REGISTRY_H__ +#define BOTAN_ALGO_REGISTRY_H__ + +#include <botan/types.h> +#include <functional> +#include <stdexcept> +#include <mutex> +#include <map> + +namespace Botan { + +size_t static_provider_weight(const std::string& prov_name); + +template<typename T> +class Algo_Registry + { + public: + typedef typename T::Spec Spec; + + typedef std::function<T* (const Spec&)> maker_fn; + + static Algo_Registry<T>& global_registry() + { + static Algo_Registry<T> g_registry; + return g_registry; + } + + void add(const std::string& name, const std::string& provider, maker_fn fn) + { + std::unique_lock<std::mutex> lock(m_mutex); + // TODO: check for duplicated registrations + m_maker_fns[name][provider] = fn; + } + + T* make(const Spec& spec, const std::string& provider = "") + { + maker_fn maker = find_maker(spec, provider); + + try + { + return maker(spec); + } + catch(std::exception& e) + { + throw std::runtime_error("Creating '" + spec.as_string() + "' failed: " + e.what()); + } + } + + class Add + { + public: + Add(const std::string& basename, maker_fn fn, const std::string& provider = "builtin") + { + Algo_Registry<T>::global_registry().add(basename, provider, fn); + } + + Add(bool cond, const std::string& basename, maker_fn fn, const std::string& provider) + { + if(cond) + Algo_Registry<T>::global_registry().add(basename, provider, fn); + } + }; + + private: + Algo_Registry() {} + + maker_fn find_maker(const Spec& spec, const std::string& provider) + { + const std::string basename = spec.algo_name(); + + std::unique_lock<std::mutex> lock(m_mutex); + auto providers = m_maker_fns.find(basename); + + if(providers != m_maker_fns.end() && !providers->second.empty()) + { + const std::map<std::string, maker_fn>& prov = providers->second; + + if(provider != "") + { + // find one explicit provider requested by user, or fail + auto i = prov.find(provider); + if(i != prov.end()) + return i->second; + } + else + { + if(prov.size() == 1) + { + return prov.begin()->second; + } + else if(prov.size() > 1) + { + // TODO choose best of available options (how?) + //throw std::runtime_error("multiple choice not implemented"); + return prov.begin()->second; + } + } + } + // Default result is a function producing a null pointer + return [](const Spec&) { return nullptr; }; + } + + std::mutex m_mutex; + std::map<std::string, std::map<std::string, maker_fn>> m_maker_fns; + }; + +template<typename T> T* +make_new_T(const typename Algo_Registry<T>::Spec&) { return new T; } + +template<typename T, size_t DEF_VAL> T* +make_new_T_1len(const typename Algo_Registry<T>::Spec& spec) + { + return new T(spec.arg_as_integer(0, DEF_VAL)); + } + +template<typename T> T* +make_new_T_1str(const typename Algo_Registry<T>::Spec& spec, const std::string& def) + { + return new T(spec.arg(0, def)); + } + +#define BOTAN_REGISTER_NAMED_T(T, namestr, type, maker) \ + namespace { Algo_Registry<T>::Add g_ ## type ## _reg(namestr, maker); } +#define BOTAN_REGISTER_T(T, name, maker) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, maker); } +#define BOTAN_REGISTER_T_NOARGS(T, name) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, make_new_T<name>); } +#define BOTAN_REGISTER_T_1LEN(T, name, def) \ + namespace { Algo_Registry<T>::Add g_ ## name ## _reg(#name, make_new_T_1len<name, def>); } + +#define BOTAN_COND_REGISTER_NAMED_T_NOARGS(cond, T, type, name, provider) \ + namespace { Algo_Registry<T>::Add g_ ## type ## _reg(cond, name, make_new_T<type>, provider); } + +// TODO move elsewhere: +#define BOTAN_REGISTER_TRANSFORM(name, maker) BOTAN_REGISTER_T(Transform, name, maker) +#define BOTAN_REGISTER_TRANSFORM_NOARGS(name) BOTAN_REGISTER_T_NOARGS(Transform, name) + +} + +#endif diff --git a/src/lib/algo_base/scan_name.cpp b/src/lib/algo_base/scan_name.cpp index 063900aae..ad34e05c1 100644 --- a/src/lib/algo_base/scan_name.cpp +++ b/src/lib/algo_base/scan_name.cpp @@ -65,6 +65,11 @@ deref_aliases(const std::pair<size_t, std::string>& in) std::mutex SCAN_Name::s_alias_map_mutex; std::map<std::string, std::string> SCAN_Name::s_alias_map; +SCAN_Name::SCAN_Name(std::string algo_spec, const std::string& extra) : SCAN_Name(algo_spec) + { + alg_name += extra; + } + SCAN_Name::SCAN_Name(std::string algo_spec) { orig_algo_spec = algo_spec; @@ -73,7 +78,7 @@ SCAN_Name::SCAN_Name(std::string algo_spec) size_t level = 0; std::pair<size_t, std::string> accum = std::make_pair(level, ""); - std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; + const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': "; algo_spec = SCAN_Name::deref_alias(algo_spec); @@ -130,12 +135,9 @@ SCAN_Name::SCAN_Name(std::string algo_spec) } } -std::string SCAN_Name::algo_name_and_args() const +std::string SCAN_Name::all_arguments() const { std::string out; - - out = algo_name(); - if(arg_count()) { out += '('; @@ -146,16 +148,14 @@ std::string SCAN_Name::algo_name_and_args() const out += ','; } out += ')'; - } - return out; } std::string SCAN_Name::arg(size_t i) const { if(i >= arg_count()) - throw std::range_error("SCAN_Name::argument - i out of range"); + throw std::range_error("SCAN_Name::arg - i out of range"); return args[i]; } diff --git a/src/lib/algo_base/scan_name.h b/src/lib/algo_base/scan_name.h index eb64f94eb..82be8d49c 100644 --- a/src/lib/algo_base/scan_name.h +++ b/src/lib/algo_base/scan_name.h @@ -29,19 +29,29 @@ class BOTAN_DLL SCAN_Name SCAN_Name(std::string algo_spec); /** + * @param algo_spec A SCAN-format name + */ + SCAN_Name(std::string algo_spec, const std::string& extra); + + /** * @return original input string */ - std::string as_string() const { return orig_algo_spec; } + const std::string& as_string() const { return orig_algo_spec; } /** * @return algorithm name */ - std::string algo_name() const { return alg_name; } + const std::string& algo_name() const { return alg_name; } /** * @return algorithm name plus any arguments */ - std::string algo_name_and_args() const; + std::string algo_name_and_args() const { return algo_name() + all_arguments(); } + + /** + * @return all arguments + */ + std::string all_arguments() const; /** * @return number of arguments diff --git a/src/lib/algo_base/transform.h b/src/lib/algo_base/transform.h index 444622b74..75bd5004a 100644 --- a/src/lib/algo_base/transform.h +++ b/src/lib/algo_base/transform.h @@ -1,5 +1,5 @@ /* -* Transformations of data +* Transforms of data * (C) 2013 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) @@ -12,6 +12,7 @@ #include <botan/key_spec.h> #include <botan/exceptn.h> #include <botan/symkey.h> +#include <botan/scan_name.h> #include <string> #include <vector> @@ -20,9 +21,11 @@ namespace Botan { /** * Interface for general transformations on data */ -class BOTAN_DLL Transformation +class BOTAN_DLL Transform { public: + typedef SCAN_Name Spec; + /** * Begin processing a message. * @param nonce the per message nonce @@ -38,7 +41,7 @@ class BOTAN_DLL Transformation * @param nonce the per message nonce */ template<typename Alloc> - BOTAN_DEPRECATED("Use Transformation::start") + BOTAN_DEPRECATED("Use Transform::start") secure_vector<byte> start_vec(const std::vector<byte, Alloc>& nonce) { return start(&nonce[0], nonce.size()); @@ -120,10 +123,10 @@ class BOTAN_DLL Transformation virtual void clear() = 0; - virtual ~Transformation() {} + virtual ~Transform() {} }; -class BOTAN_DLL Keyed_Transform : public Transformation +class BOTAN_DLL Keyed_Transform : public Transform { public: /** @@ -168,6 +171,12 @@ class BOTAN_DLL Keyed_Transform : public Transformation virtual void key_schedule(const byte key[], size_t length) = 0; }; +typedef Transform Transformation; + +BOTAN_DLL Transform* get_transform(const std::string& specstr, + const std::string& provider = "", + const std::string& dirstr = ""); + } #endif |