aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/base/algo_registry.h299
-rw-r--r--src/lib/base/info.txt4
-rw-r--r--src/lib/base/scan_name.cpp78
-rw-r--r--src/lib/base/scan_name.h45
-rw-r--r--src/lib/block/block_cipher.cpp232
-rw-r--r--src/lib/block/block_cipher.h18
-rw-r--r--src/lib/block/cascade/cascade.cpp10
-rw-r--r--src/lib/block/cascade/cascade.h2
-rw-r--r--src/lib/block/lion/lion.cpp16
-rw-r--r--src/lib/block/lion/lion.h2
-rw-r--r--src/lib/compression/bzip2/bzip2.cpp3
-rw-r--r--src/lib/compression/compress_utils.cpp189
-rw-r--r--src/lib/compression/compress_utils.h5
-rw-r--r--src/lib/compression/compression.cpp266
-rw-r--r--src/lib/compression/compression.h10
-rw-r--r--src/lib/compression/lzma/lzma.cpp3
-rw-r--r--src/lib/compression/zlib/zlib.cpp5
-rw-r--r--src/lib/filters/filters.h2
-rw-r--r--src/lib/hash/blake2/blake2b.cpp5
-rw-r--r--src/lib/hash/blake2/blake2b.h2
-rw-r--r--src/lib/hash/comb4p/comb4p.cpp13
-rw-r--r--src/lib/hash/comb4p/comb4p.h2
-rw-r--r--src/lib/hash/hash.cpp231
-rw-r--r--src/lib/hash/hash.h21
-rw-r--r--src/lib/hash/par_hash/par_hash.cpp28
-rw-r--r--src/lib/hash/par_hash/par_hash.h5
-rw-r--r--src/lib/hash/skein/skein_512.cpp5
-rw-r--r--src/lib/hash/skein/skein_512.h2
-rw-r--r--src/lib/kdf/hkdf/hkdf.cpp11
-rw-r--r--src/lib/kdf/hkdf/hkdf.h2
-rw-r--r--src/lib/kdf/kdf.cpp183
-rw-r--r--src/lib/kdf/kdf.h19
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.cpp11
-rw-r--r--src/lib/kdf/prf_tls/prf_tls.h2
-rw-r--r--src/lib/kdf/sp800_108/sp800_108.cpp33
-rw-r--r--src/lib/kdf/sp800_108/sp800_108.h5
-rw-r--r--src/lib/kdf/sp800_56c/sp800_56c.cpp14
-rw-r--r--src/lib/kdf/sp800_56c/sp800_56c.h2
-rw-r--r--src/lib/mac/cbc_mac/cbc_mac.cpp10
-rw-r--r--src/lib/mac/cbc_mac/cbc_mac.h2
-rw-r--r--src/lib/mac/cmac/cmac.cpp10
-rw-r--r--src/lib/mac/cmac/cmac.h2
-rw-r--r--src/lib/mac/hmac/hmac.cpp10
-rw-r--r--src/lib/mac/hmac/hmac.h2
-rw-r--r--src/lib/mac/mac.cpp117
-rw-r--r--src/lib/mac/mac.h21
-rw-r--r--src/lib/modes/aead/aead.cpp119
-rw-r--r--src/lib/modes/aead/aead.h2
-rw-r--r--src/lib/modes/aead/ccm/ccm.cpp1
-rw-r--r--src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp1
-rw-r--r--src/lib/modes/aead/eax/eax.cpp1
-rw-r--r--src/lib/modes/aead/gcm/gcm.cpp2
-rw-r--r--src/lib/modes/aead/ocb/ocb.cpp2
-rw-r--r--src/lib/modes/aead/siv/siv.cpp1
-rw-r--r--src/lib/modes/cbc/cbc.cpp2
-rw-r--r--src/lib/modes/cfb/cfb.cpp1
-rw-r--r--src/lib/modes/cipher_mode.cpp190
-rw-r--r--src/lib/modes/cipher_mode.h3
-rw-r--r--src/lib/modes/ecb/ecb.cpp2
-rw-r--r--src/lib/modes/info.txt4
-rw-r--r--src/lib/modes/mode_utils.h67
-rw-r--r--src/lib/modes/xts/xts.cpp2
-rw-r--r--src/lib/pbkdf/pbkdf.cpp44
-rw-r--r--src/lib/pbkdf/pbkdf.h4
-rw-r--r--src/lib/pbkdf/pbkdf2/pbkdf2.cpp11
-rw-r--r--src/lib/pbkdf/pbkdf2/pbkdf2.h2
-rw-r--r--src/lib/pk_pad/eme.cpp44
-rw-r--r--src/lib/pk_pad/eme.h3
-rw-r--r--src/lib/pk_pad/eme_oaep/oaep.cpp15
-rw-r--r--src/lib/pk_pad/eme_oaep/oaep.h2
-rw-r--r--src/lib/pk_pad/emsa.cpp106
-rw-r--r--src/lib/pk_pad/emsa.h3
-rw-r--r--src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp12
-rw-r--r--src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h2
-rw-r--r--src/lib/pk_pad/emsa_pssr/pssr.cpp14
-rw-r--r--src/lib/pk_pad/emsa_pssr/pssr.h2
-rw-r--r--src/lib/prov/openssl/openssl.h33
-rw-r--r--src/lib/prov/openssl/openssl_block.cpp120
-rw-r--r--src/lib/prov/openssl/openssl_ec.cpp25
-rw-r--r--src/lib/prov/openssl/openssl_hash.cpp66
-rw-r--r--src/lib/prov/openssl/openssl_rc4.cpp14
-rw-r--r--src/lib/prov/pkcs11/p11_ecdh.cpp1
-rw-r--r--src/lib/prov/pkcs11/p11_ecdsa.cpp1
-rw-r--r--src/lib/prov/pkcs11/p11_rsa.cpp1
-rw-r--r--src/lib/stream/ctr/ctr.cpp10
-rw-r--r--src/lib/stream/ctr/ctr.h2
-rw-r--r--src/lib/stream/ofb/ofb.cpp10
-rw-r--r--src/lib/stream/ofb/ofb.h2
-rw-r--r--src/lib/stream/rc4/rc4.cpp14
-rw-r--r--src/lib/stream/rc4/rc4.h2
-rw-r--r--src/lib/stream/stream_cipher.cpp100
-rw-r--r--src/lib/stream/stream_cipher.h23
-rw-r--r--src/lib/utils/exceptn.h7
-rw-r--r--src/tests/test_ecies.cpp2
-rw-r--r--src/tests/test_hash.cpp102
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
-
}
}