aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/algo_base
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/algo_base')
-rw-r--r--src/lib/algo_base/algo_registry.cpp20
-rw-r--r--src/lib/algo_base/algo_registry.h146
-rw-r--r--src/lib/algo_base/scan_name.cpp16
-rw-r--r--src/lib/algo_base/scan_name.h16
-rw-r--r--src/lib/algo_base/transform.h19
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