aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstate
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-11-09 19:49:23 +0000
committerlloyd <[email protected]>2008-11-09 19:49:23 +0000
commitcec305c17354fca9c426d76a78f7088f60607afb (patch)
tree1bf7b53a76617339d67523d34be34f903ced28fc /src/libstate
parentb01c1d79f02de8ca5c02f08e73cedeadc4d0753a (diff)
Move engine to libstate/ directory, since there is a mutual dependency
(messy). Remove unused libstate.h includes from a few files.
Diffstat (limited to 'src/libstate')
-rw-r--r--src/libstate/engine/def_engine/def_eng.h74
-rw-r--r--src/libstate/engine/def_engine/def_mode.cpp180
-rw-r--r--src/libstate/engine/def_engine/def_pk_ops.cpp119
-rw-r--r--src/libstate/engine/def_engine/def_powm.cpp22
-rw-r--r--src/libstate/engine/def_engine/info.txt16
-rw-r--r--src/libstate/engine/def_engine/lookup_cipher.cpp351
-rw-r--r--src/libstate/engine/def_engine/lookup_hash.cpp216
-rw-r--r--src/libstate/engine/def_engine/lookup_mac.cpp92
-rw-r--r--src/libstate/engine/def_engine/lookup_s2k.cpp67
-rw-r--r--src/libstate/engine/engine.cpp358
-rw-r--r--src/libstate/engine/engine.h225
-rw-r--r--src/libstate/engine/gnump/eng_gmp.h53
-rw-r--r--src/libstate/engine/gnump/gmp_dh.cpp51
-rw-r--r--src/libstate/engine/gnump/gmp_dsa.cpp122
-rw-r--r--src/libstate/engine/gnump/gmp_elg.cpp90
-rw-r--r--src/libstate/engine/gnump/gmp_if.cpp79
-rw-r--r--src/libstate/engine/gnump/gmp_mem.cpp68
-rw-r--r--src/libstate/engine/gnump/gmp_nr.cpp105
-rw-r--r--src/libstate/engine/gnump/gmp_powm.cpp51
-rw-r--r--src/libstate/engine/gnump/gmp_wrap.cpp96
-rw-r--r--src/libstate/engine/gnump/gmp_wrap.h36
-rw-r--r--src/libstate/engine/gnump/info.txt26
-rw-r--r--src/libstate/engine/info.txt10
-rw-r--r--src/libstate/engine/openssl/bn_powm.cpp52
-rw-r--r--src/libstate/engine/openssl/bn_wrap.cpp114
-rw-r--r--src/libstate/engine/openssl/bn_wrap.h51
-rw-r--r--src/libstate/engine/openssl/eng_ossl.h53
-rw-r--r--src/libstate/engine/openssl/info.txt28
-rw-r--r--src/libstate/engine/openssl/ossl_bc.cpp204
-rw-r--r--src/libstate/engine/openssl/ossl_dh.cpp58
-rw-r--r--src/libstate/engine/openssl/ossl_dsa.cpp124
-rw-r--r--src/libstate/engine/openssl/ossl_elg.cpp93
-rw-r--r--src/libstate/engine/openssl/ossl_if.cpp83
-rw-r--r--src/libstate/engine/openssl/ossl_md.cpp121
-rw-r--r--src/libstate/engine/openssl/ossl_nr.cpp111
-rw-r--r--src/libstate/engine/openssl/ossl_rc4.cpp92
36 files changed, 3691 insertions, 0 deletions
diff --git a/src/libstate/engine/def_engine/def_eng.h b/src/libstate/engine/def_engine/def_eng.h
new file mode 100644
index 000000000..3d3fba809
--- /dev/null
+++ b/src/libstate/engine/def_engine/def_eng.h
@@ -0,0 +1,74 @@
+/*************************************************
+* Default Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_DEFAULT_ENGINE_H__
+#define BOTAN_DEFAULT_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*************************************************
+* Default Engine *
+*************************************************/
+class BOTAN_DLL Default_Engine : public Engine
+ {
+ public:
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ virtual bool can_add_algorithms() { return true; }
+
+ Keyed_Filter* get_cipher(const std::string&, Cipher_Dir);
+ private:
+ BlockCipher* find_block_cipher(const std::string&) const;
+ StreamCipher* find_stream_cipher(const std::string&) const;
+ HashFunction* find_hash(const std::string&) const;
+ MessageAuthenticationCode* find_mac(const std::string&) const;
+
+ class S2K* find_s2k(const std::string&) const;
+ class BlockCipherModePaddingMethod*
+ find_bc_pad(const std::string&) const;
+ };
+
+}
+
+#endif
diff --git a/src/libstate/engine/def_engine/def_mode.cpp b/src/libstate/engine/def_engine/def_mode.cpp
new file mode 100644
index 000000000..1148d6312
--- /dev/null
+++ b/src/libstate/engine/def_engine/def_mode.cpp
@@ -0,0 +1,180 @@
+/*************************************************
+* Default Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/parsing.h>
+#include <botan/filters.h>
+#include <botan/lookup.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_ECB)
+ #include <botan/ecb.h>
+#endif
+
+#if defined(BOTAN_HAS_CBC)
+ #include <botan/cbc.h>
+#endif
+
+#if defined(BOTAN_HAS_CTS)
+ #include <botan/cts.h>
+#endif
+
+#if defined(BOTAN_HAS_CFB)
+ #include <botan/cfb.h>
+#endif
+
+#if defined(BOTAN_HAS_OFB)
+ #include <botan/ofb.h>
+#endif
+
+#if defined(BOTAN_HAS_CTR)
+ #include <botan/ctr.h>
+#endif
+
+#if defined(BOTAN_HAS_EAX)
+ #include <botan/eax.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Get a cipher object *
+*************************************************/
+Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction)
+ {
+ std::vector<std::string> algo_parts = split_on(algo_spec, '/');
+ if(algo_parts.empty())
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ const std::string cipher_name = algo_parts[0];
+
+ if(have_stream_cipher(cipher_name))
+ {
+ if(algo_parts.size() == 1)
+ return new StreamCipher_Filter(cipher_name);
+ return 0;
+ }
+
+ if(!have_block_cipher(cipher_name))
+ return 0;
+
+ std::auto_ptr<BlockCipher> cipher(get_block_cipher(cipher_name));
+
+ if(algo_parts.size() != 2 && algo_parts.size() != 3)
+ return 0;
+
+ std::string mode = algo_parts[1];
+ u32bit bits = 0;
+
+ if(mode.find("CFB") != std::string::npos ||
+ mode.find("EAX") != std::string::npos)
+ {
+ std::vector<std::string> algo_info = parse_algorithm_name(mode);
+ mode = algo_info[0];
+ if(algo_info.size() == 1)
+ bits = 8*cipher->BLOCK_SIZE;
+ else if(algo_info.size() == 2)
+ bits = to_u32bit(algo_info[1]);
+ else
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+
+ std::string padding;
+ if(algo_parts.size() == 3)
+ padding = algo_parts[2];
+ else
+ padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
+
+ if(mode == "ECB" && padding == "CTS")
+ return 0;
+ else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ if(mode == "OFB")
+ {
+#if defined(BOTAN_HAS_OFB)
+ return new OFB(cipher.release());
+#else
+ return 0;
+#endif
+ }
+
+ if(mode == "CTR-BE")
+ {
+#if defined(BOTAN_HAS_CTR)
+ return new CTR_BE(cipher.release());
+#else
+ return 0;
+#endif
+ }
+
+ if(mode == "ECB")
+ {
+#if defined(BOTAN_HAS_ECB)
+ if(direction == ENCRYPTION)
+ return new ECB_Encryption(cipher.release(), get_bc_pad(padding));
+ else
+ return new ECB_Decryption(cipher.release(), get_bc_pad(padding));
+#else
+ return 0;
+#endif
+ }
+
+ if(mode == "CFB")
+ {
+#if defined(BOTAN_HAS_CFB)
+ if(direction == ENCRYPTION)
+ return new CFB_Encryption(cipher.release(), bits);
+ else
+ return new CFB_Decryption(cipher.release(), bits);
+#else
+ return 0;
+#endif
+ }
+
+ if(mode == "CBC")
+ {
+ if(padding == "CTS")
+ {
+#if defined(BOTAN_HAS_CTS)
+ if(direction == ENCRYPTION)
+ return new CTS_Encryption(cipher.release());
+ else
+ return new CTS_Decryption(cipher.release());
+#else
+ return 0;
+#endif
+ }
+
+#if defined(BOTAN_HAS_CBC)
+ if(direction == ENCRYPTION)
+ return new CBC_Encryption(cipher.release(),
+ get_bc_pad(padding));
+ else
+ return new CBC_Decryption(cipher.release(),
+ get_bc_pad(padding));
+#else
+ return 0;
+#endif
+ }
+
+ if(mode == "EAX")
+ {
+#if defined(BOTAN_HAS_EAX)
+ if(direction == ENCRYPTION)
+ return new EAX_Encryption(cipher.release(), bits);
+ else
+ return new EAX_Decryption(cipher.release(), bits);
+#else
+ return 0;
+#endif
+ }
+
+ throw Algorithm_Not_Found("get_mode: " + cipher_name + "/" +
+ mode + "/" + padding);
+ }
+
+}
diff --git a/src/libstate/engine/def_engine/def_pk_ops.cpp b/src/libstate/engine/def_engine/def_pk_ops.cpp
new file mode 100644
index 000000000..5e29e110f
--- /dev/null
+++ b/src/libstate/engine/def_engine/def_pk_ops.cpp
@@ -0,0 +1,119 @@
+/*************************************************
+* PK Operations Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new Default_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_DSA_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_NR_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new Default_ELG_Op(group, y, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* Default_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new Default_DH_Op(group, x);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+/*************************************************
+* Acquire a ECDSA op *
+*************************************************/
+ECDSA_Operation* Default_Engine::ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key) const
+ {
+ return new Default_ECDSA_Op(dom_pars, priv_key, pub_key);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+/*************************************************
+* Acquire a ECKAEG op *
+*************************************************/
+ECKAEG_Operation* Default_Engine::eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key) const
+ {
+ return new Default_ECKAEG_Op(dom_pars, priv_key, pub_key);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/def_engine/def_powm.cpp b/src/libstate/engine/def_engine/def_powm.cpp
new file mode 100644
index 000000000..38aca901c
--- /dev/null
+++ b/src/libstate/engine/def_engine/def_powm.cpp
@@ -0,0 +1,22 @@
+/*************************************************
+* Modular Exponentiation Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/def_powm.h>
+
+namespace Botan {
+
+/*************************************************
+* Choose a modular exponentation algorithm *
+*************************************************/
+Modular_Exponentiator*
+Default_Engine::mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints) const
+ {
+ if(n.is_odd())
+ return new Montgomery_Exponentiator(n, hints);
+ return new Fixed_Window_Exponentiator(n, hints);
+ }
+
+}
diff --git a/src/libstate/engine/def_engine/info.txt b/src/libstate/engine/def_engine/info.txt
new file mode 100644
index 000000000..0de7f37ab
--- /dev/null
+++ b/src/libstate/engine/def_engine/info.txt
@@ -0,0 +1,16 @@
+realname "Default Engine"
+
+define DEFAULT_ENGINE
+
+load_on auto
+
+<add>
+def_mode.cpp
+def_powm.cpp
+def_eng.h
+lookup_cipher.cpp
+lookup_hash.cpp
+lookup_mac.cpp
+lookup_s2k.cpp
+def_pk_ops.cpp
+</add>
diff --git a/src/libstate/engine/def_engine/lookup_cipher.cpp b/src/libstate/engine/def_engine/lookup_cipher.cpp
new file mode 100644
index 000000000..57dbbe60e
--- /dev/null
+++ b/src/libstate/engine/def_engine/lookup_cipher.cpp
@@ -0,0 +1,351 @@
+/*************************************************
+* Cipher Lookup *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ #include <botan/blowfish.h>
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ #include <botan/cast128.h>
+ #include <botan/cast256.h>
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ #include <botan/des.h>
+ #include <botan/desx.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST)
+ #include <botan/gost.h>
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ #include <botan/idea.h>
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ #include <botan/kasumi.h>
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ #include <botan/lion.h>
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ #include <botan/lubyrack.h>
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ #include <botan/mars.h>
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ #include <botan/misty1.h>
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ #include <botan/noekeon.h>
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ #include <botan/rc2.h>
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ #include <botan/rc5.h>
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ #include <botan/rc6.h>
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ #include <botan/safer_sk.h>
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ #include <botan/seed.h>
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ #include <botan/serpent.h>
+#endif
+
+#if defined(BOTAN_HAS_SERPENT_IA32)
+ #include <botan/serp_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ #include <botan/skipjack.h>
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ #include <botan/square.h>
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ #include <botan/tea.h>
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ #include <botan/twofish.h>
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ #include <botan/xtea.h>
+#endif
+
+#if defined(BOTAN_HAS_ARC4)
+ #include <botan/arc4.h>
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ #include <botan/salsa20.h>
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ #include <botan/turing.h>
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ #include <botan/wid_wake.h>
+#endif
+
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ #include <botan/mode_pad.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Some macros to simplify control flow *
+*************************************************/
+#define HANDLE_TYPE_NO_ARGS(NAME, TYPE) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE; \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ if(name.size() == 3) \
+ return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipher*
+Default_Engine::find_block_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_AES)
+ HANDLE_TYPE_NO_ARGS("AES", AES);
+ HANDLE_TYPE_NO_ARGS("AES-128", AES_128);
+ HANDLE_TYPE_NO_ARGS("AES-192", AES_192);
+ HANDLE_TYPE_NO_ARGS("AES-256", AES_256);
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ HANDLE_TYPE_NO_ARGS("Blowfish", Blowfish);
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ HANDLE_TYPE_NO_ARGS("CAST-128", CAST_128);
+ HANDLE_TYPE_NO_ARGS("CAST-256", CAST_256);
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ HANDLE_TYPE_NO_ARGS("DES", DES);
+ HANDLE_TYPE_NO_ARGS("DESX", DESX);
+ HANDLE_TYPE_NO_ARGS("TripleDES", TripleDES);
+#endif
+
+#if defined(BOTAN_HAS_GOST)
+ HANDLE_TYPE_NO_ARGS("GOST", GOST);
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ HANDLE_TYPE_NO_ARGS("IDEA", IDEA);
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ HANDLE_TYPE_NO_ARGS("KASUMI", KASUMI);
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ HANDLE_TYPE_NO_ARGS("MARS", MARS);
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ HANDLE_TYPE_ONE_U32BIT("MISTY1", MISTY1, 8);
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ HANDLE_TYPE_NO_ARGS("Noekeon", Noekeon);
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ HANDLE_TYPE_NO_ARGS("RC2", RC2);
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ HANDLE_TYPE_ONE_U32BIT("RC5", RC5, 12);
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ HANDLE_TYPE_NO_ARGS("RC6", RC6);
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ HANDLE_TYPE_ONE_U32BIT("SAFER-SK", SAFER_SK, 10);
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ HANDLE_TYPE_NO_ARGS("SEED", SEED);
+#endif
+
+#if defined(BOTAN_HAS_SERPENT_IA32)
+ HANDLE_TYPE_NO_ARGS("Serpent", Serpent_IA32);
+#elif defined(BOTAN_HAS_SERPENT)
+ HANDLE_TYPE_NO_ARGS("Serpent", Serpent);
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ HANDLE_TYPE_NO_ARGS("Skipjack", Skipjack);
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ HANDLE_TYPE_NO_ARGS("Square", Square);
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ HANDLE_TYPE_NO_ARGS("TEA", TEA);
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ HANDLE_TYPE_NO_ARGS("Twofish", Twofish);
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ HANDLE_TYPE_NO_ARGS("XTEA", XTEA);
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ if(algo_name == "Luby-Rackoff" && name.size() >= 2)
+ {
+ HashFunction* hash = get_hash(name[1]);
+ if(hash)
+ return new LubyRackoff(hash);
+ }
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ if(algo_name == "Lion")
+ {
+ if(name.size() != 4)
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ std::auto_ptr<HashFunction> hash(get_hash(name[1]));
+ if(!hash.get())
+ throw Algorithm_Not_Found(name[1]);
+
+ std::auto_ptr<StreamCipher> sc(get_stream_cipher(name[2]));
+ if(!sc.get())
+ throw Algorithm_Not_Found(name[2]);
+
+ return new Lion(hash.release(), sc.release(), to_u32bit(name[3]));
+ }
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+StreamCipher*
+Default_Engine::find_stream_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_ARC4)
+ HANDLE_TYPE_ONE_U32BIT("ARC4", ARC4, 0);
+ HANDLE_TYPE_ONE_U32BIT("RC4_drop", ARC4, 768);
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ HANDLE_TYPE_NO_ARGS("Salsa20", Salsa20);
+#endif
+
+#if defined(BOTAN_HAS_TURING)
+ HANDLE_TYPE_NO_ARGS("Turing", Turing);
+#endif
+
+#if defined(BOTAN_HAS_WID_WAKE)
+ HANDLE_TYPE_NO_ARGS("WiderWake4+1-BE", WiderWake_41_BE);
+#endif
+
+ return 0;
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipherModePaddingMethod*
+Default_Engine::find_bc_pad(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ HANDLE_TYPE_NO_ARGS("PKCS7", PKCS7_Padding);
+ HANDLE_TYPE_NO_ARGS("OneAndZeros", OneAndZeros_Padding);
+ HANDLE_TYPE_NO_ARGS("X9.23", ANSI_X923_Padding);
+ HANDLE_TYPE_NO_ARGS("NoPadding", Null_Padding);
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/def_engine/lookup_hash.cpp b/src/libstate/engine/def_engine/lookup_hash.cpp
new file mode 100644
index 000000000..10cc86785
--- /dev/null
+++ b/src/libstate/engine/def_engine/lookup_hash.cpp
@@ -0,0 +1,216 @@
+/*************************************************
+* Hash Algorithms Lookup *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_ADLER32)
+ #include <botan/adler32.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ #include <botan/crc24.h>
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ #include <botan/crc32.h>
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ #include <botan/fork256.h>
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ #include <botan/has160.h>
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ #include <botan/md2.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ #include <botan/md4.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4_IA32)
+ #include <botan/md4_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ #include <botan/md5.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5_IA32)
+ #include <botan/md5_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ #include <botan/rmd128.h>
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ #include <botan/rmd160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ #include <botan/sha160.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_IA32)
+ #include <botan/sha1_ia32.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ #include <botan/sha1_sse2.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_AMD64)
+ #include <botan/sha1_amd64.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ #include <botan/sha2_32.h>
+ #include <botan/sha2_64.h>
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ #include <botan/tiger.h>
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ #include <botan/whrlpool.h>
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+ #include <botan/par_hash.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Some macros to simplify control flow *
+*************************************************/
+#define HANDLE_TYPE_NO_ARGS(NAME, TYPE) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE; \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ if(name.size() == 3) \
+ return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+HashFunction*
+Default_Engine::find_hash(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_ADLER32)
+ HANDLE_TYPE_NO_ARGS("Adler32", Adler32);
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ HANDLE_TYPE_NO_ARGS("CRC24", CRC24);
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ HANDLE_TYPE_NO_ARGS("CRC32", CRC32);
+#endif
+
+#if defined(BOTAN_HAS_FORK_256)
+ HANDLE_TYPE_NO_ARGS("FORK-256", FORK_256);
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ HANDLE_TYPE_NO_ARGS("HAS-160", HAS_160);
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ HANDLE_TYPE_NO_ARGS("MD2", MD2);
+#endif
+
+#if defined(BOTAN_HAS_MD4_IA32)
+ HANDLE_TYPE_NO_ARGS("MD4", MD4_IA32);
+#elif defined(BOTAN_HAS_MD4)
+ HANDLE_TYPE_NO_ARGS("MD4", MD4);
+#endif
+
+#if defined(BOTAN_HAS_MD5_IA32)
+ HANDLE_TYPE_NO_ARGS("MD5", MD5_IA32);
+#elif defined(BOTAN_HAS_MD5)
+ HANDLE_TYPE_NO_ARGS("MD5", MD5);
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ HANDLE_TYPE_NO_ARGS("RIPEMD-128", RIPEMD_128);
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ HANDLE_TYPE_NO_ARGS("RIPEMD-160", RIPEMD_160);
+#endif
+
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160_SSE2);
+#elif defined(BOTAN_HAS_SHA1_AMD64)
+ HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160_AMD64);
+#elif defined(BOTAN_HAS_SHA1_IA32)
+ HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160_IA32);
+#elif defined(BOTAN_HAS_SHA1)
+ HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160);
+#endif
+
+#if defined(BOTAN_HAS_SHA2)
+ HANDLE_TYPE_NO_ARGS("SHA-224", SHA_224);
+ HANDLE_TYPE_NO_ARGS("SHA-256", SHA_256);
+ HANDLE_TYPE_NO_ARGS("SHA-384", SHA_384);
+ HANDLE_TYPE_NO_ARGS("SHA-512", SHA_512);
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ HANDLE_TYPE_TWO_U32BIT("Tiger", Tiger, 24);
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ HANDLE_TYPE_NO_ARGS("Whirlpool", Whirlpool);
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+ if(algo_name == "Parallel")
+ {
+ if(name.size() < 2)
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ std::vector<HashFunction*> hashes;
+
+ for(u32bit i = 1; i != name.size(); ++i)
+ hashes.push_back(get_hash(name[i]));
+
+ return new Parallel(hashes);
+ }
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/def_engine/lookup_mac.cpp b/src/libstate/engine/def_engine/lookup_mac.cpp
new file mode 100644
index 000000000..db80d525f
--- /dev/null
+++ b/src/libstate/engine/def_engine/lookup_mac.cpp
@@ -0,0 +1,92 @@
+/*************************************************
+* MAC Lookup *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ #include <botan/cbc_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ #include <botan/cmac.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ #include <botan/hmac.h>
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ #include <botan/ssl3_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ #include <botan/x919_mac.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+MessageAuthenticationCode*
+Default_Engine::find_mac(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ if(algo_name == "CBC-MAC")
+ {
+ if(name.size() == 2)
+ return new CBC_MAC(get_block_cipher(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ if(algo_name == "CMAC")
+ {
+ if(name.size() == 2)
+ return new CMAC(get_block_cipher(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ if(algo_name == "HMAC")
+ {
+ if(name.size() == 2)
+ return new HMAC(get_hash(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ if(algo_name == "SSL3-MAC")
+ {
+ if(name.size() == 2)
+ return new SSL3_MAC(get_hash(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ if(algo_name == "X9.19-MAC")
+ {
+ if(name.size() == 1)
+ return new ANSI_X919_MAC(get_block_cipher("DES"));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/def_engine/lookup_s2k.cpp b/src/libstate/engine/def_engine/lookup_s2k.cpp
new file mode 100644
index 000000000..2f33ef6fc
--- /dev/null
+++ b/src/libstate/engine/def_engine/lookup_s2k.cpp
@@ -0,0 +1,67 @@
+/*************************************************
+* S2K Lookup *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/def_eng.h>
+#include <botan/lookup.h>
+#include <botan/libstate.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_PBKDF1)
+ #include <botan/pbkdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ #include <botan/pbkdf2.h>
+ #include <botan/hmac.h>
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ #include <botan/pgp_s2k.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+S2K* Default_Engine::find_s2k(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.empty())
+ return 0;
+
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#if defined(BOTAN_HAS_PBKDF1)
+ if(algo_name == "PBKDF1")
+ {
+ if(name.size() == 2)
+ return new PKCS5_PBKDF1(get_hash(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ if(algo_name == "PBKDF2")
+ {
+ if(name.size() == 2)
+ return new PKCS5_PBKDF2(new HMAC(get_hash(name[1])));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+#if defined(BOTAN_HAS_PGPS2K)
+ if(algo_name == "OpenPGP-S2K")
+ {
+ if(name.size() == 2)
+ return new OpenPGP_S2K(get_hash(name[1]));
+ throw Invalid_Algorithm_Name(algo_spec);
+ }
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/engine.cpp b/src/libstate/engine/engine.cpp
new file mode 100644
index 000000000..59621a7d3
--- /dev/null
+++ b/src/libstate/engine/engine.cpp
@@ -0,0 +1,358 @@
+/*************************************************
+* Basic No-Op Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/engine.h>
+#include <botan/libstate.h>
+#include <botan/stl_util.h>
+#include <botan/mode_pad.h>
+#include <botan/s2k.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Algorithm Cache *
+*************************************************/
+template<typename T>
+class Algorithm_Cache_Impl : public Engine::Algorithm_Cache<T>
+ {
+ public:
+ T* get(const std::string& name) const
+ {
+ Mutex_Holder lock(mutex);
+ return search_map(mappings, name);
+ }
+
+ void add(T* algo, const std::string& index_name = "") const
+ {
+ if(!algo)
+ return;
+
+ Mutex_Holder lock(mutex);
+
+ const std::string name =
+ (index_name != "" ? index_name : algo->name());
+
+ if(mappings.find(name) != mappings.end())
+ delete mappings[name];
+ mappings[name] = algo;
+ }
+
+ Algorithm_Cache_Impl()
+ {
+ mutex = global_state().get_mutex();
+ }
+
+ ~Algorithm_Cache_Impl()
+ {
+ typename std::map<std::string, T*>::iterator i = mappings.begin();
+
+ while(i != mappings.end())
+ {
+ delete i->second;
+ ++i;
+ }
+ delete mutex;
+ }
+ private:
+ Mutex* mutex;
+ mutable std::map<std::string, T*> mappings;
+ };
+
+}
+
+/*************************************************
+* Acquire a BlockCipher *
+*************************************************/
+const BlockCipher* Engine::block_cipher(const std::string& name) const
+ {
+ return lookup_algo(cache_of_bc, global_state().deref_alias(name),
+ this, &Engine::find_block_cipher);
+ }
+
+/*************************************************
+* Acquire a StreamCipher *
+*************************************************/
+const StreamCipher* Engine::stream_cipher(const std::string& name) const
+ {
+ return lookup_algo(cache_of_sc, global_state().deref_alias(name),
+ this, &Engine::find_stream_cipher);
+ }
+
+/*************************************************
+* Acquire a HashFunction *
+*************************************************/
+const HashFunction* Engine::hash(const std::string& name) const
+ {
+ return lookup_algo(cache_of_hf, global_state().deref_alias(name),
+ this, &Engine::find_hash);
+ }
+
+/*************************************************
+* Acquire a MessageAuthenticationCode *
+*************************************************/
+const MessageAuthenticationCode* Engine::mac(const std::string& name) const
+ {
+ return lookup_algo(cache_of_mac, global_state().deref_alias(name),
+ this, &Engine::find_mac);
+ }
+
+/*************************************************
+* Acquire a S2K object *
+*************************************************/
+const S2K* Engine::s2k(const std::string& name) const
+ {
+ return lookup_algo(cache_of_s2k, global_state().deref_alias(name),
+ this, &Engine::find_s2k);
+ }
+
+/*************************************************
+* Acquire a cipher padding object *
+*************************************************/
+const BlockCipherModePaddingMethod*
+Engine::bc_pad(const std::string& name) const
+ {
+ return lookup_algo(cache_of_bc_pad, global_state().deref_alias(name),
+ this, &Engine::find_bc_pad);
+ }
+
+/*************************************************
+* Add a block cipher to the lookup table *
+*************************************************/
+void Engine::add_algorithm(BlockCipher* algo) const
+ {
+ cache_of_bc->add(algo);
+ }
+
+/*************************************************
+* Add a stream cipher to the lookup table *
+*************************************************/
+void Engine::add_algorithm(StreamCipher* algo) const
+ {
+ cache_of_sc->add(algo);
+ }
+
+/*************************************************
+* Add a hash function to the lookup table *
+*************************************************/
+void Engine::add_algorithm(HashFunction* algo) const
+ {
+ cache_of_hf->add(algo);
+ }
+
+/*************************************************
+* Add a MAC to the lookup table *
+*************************************************/
+void Engine::add_algorithm(MessageAuthenticationCode* algo) const
+ {
+ cache_of_mac->add(algo);
+ }
+
+/*************************************************
+* Add a S2K to the lookup table *
+*************************************************/
+void Engine::add_algorithm(S2K* algo) const
+ {
+ cache_of_s2k->add(algo);
+ }
+
+/*************************************************
+* Add a cipher pad method to the lookup table *
+*************************************************/
+void Engine::add_algorithm(BlockCipherModePaddingMethod* algo) const
+ {
+ cache_of_bc_pad->add(algo);
+ }
+
+/*************************************************
+* Create an Engine *
+*************************************************/
+Engine::Engine()
+ {
+ cache_of_bc = new Algorithm_Cache_Impl<BlockCipher>();
+ cache_of_sc = new Algorithm_Cache_Impl<StreamCipher>();
+ cache_of_hf = new Algorithm_Cache_Impl<HashFunction>();
+ cache_of_mac = new Algorithm_Cache_Impl<MessageAuthenticationCode>();
+ cache_of_s2k = new Algorithm_Cache_Impl<S2K>();
+ cache_of_bc_pad =
+ new Algorithm_Cache_Impl<BlockCipherModePaddingMethod>();
+ }
+
+/*************************************************
+* Destroy an Engine *
+*************************************************/
+Engine::~Engine()
+ {
+ delete cache_of_bc;
+ delete cache_of_sc;
+ delete cache_of_hf;
+ delete cache_of_mac;
+ delete cache_of_s2k;
+ delete cache_of_bc_pad;
+ }
+
+namespace Engine_Core {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d,
+ const BigInt& p, const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ IF_Operation* op = engine->if_op(e, n, d, p, q, d1, d2, c);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ DSA_Operation* op = engine->dsa_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ NR_Operation* op = engine->nr_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ ELG_Operation* op = engine->elg_op(group, y, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* dh_op(const DL_Group& group, const BigInt& x)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ DH_Operation* op = engine->dh_op(group, x);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+/*************************************************
+* Acquire an ECDSA op *
+*************************************************/
+ECDSA_Operation* ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ ECDSA_Operation* op = engine->ecdsa_op(dom_pars, priv_key, pub_key);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::ecdsa_op: Unable to find a working engine");
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+/*************************************************
+* Acquire a ECKAEG op *
+*************************************************/
+ECKAEG_Operation* eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ ECKAEG_Operation* op = engine->eckaeg_op(dom_pars, priv_key, pub_key);
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::eckaeg_op: Unable to find a working engine");
+ }
+#endif
+
+/*************************************************
+* Acquire a modular exponentiator *
+*************************************************/
+Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints)
+ {
+ Library_State::Engine_Iterator i(global_state());
+
+ while(const Engine* engine = i.next())
+ {
+ Modular_Exponentiator* op = engine->mod_exp(n, hints);
+
+ if(op)
+ return op;
+ }
+
+ throw Lookup_Error("Engine_Core::mod_exp: Unable to find a working engine");
+ }
+
+}
+
+}
diff --git a/src/libstate/engine/engine.h b/src/libstate/engine/engine.h
new file mode 100644
index 000000000..83870bb27
--- /dev/null
+++ b/src/libstate/engine/engine.h
@@ -0,0 +1,225 @@
+/*************************************************
+* Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ENGINE_H__
+#define BOTAN_ENGINE_H__
+
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+
+#include <botan/mutex.h>
+#include <botan/pow_mod.h>
+#include <botan/basefilt.h>
+#include <utility>
+#include <map>
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ #include <botan/if_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa_op.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh_op.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elg_op.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ #include <botan/eckaeg_op.h>
+ #include <botan/ec_dompar.h>
+#endif
+
+namespace Botan {
+
+/*************************************************
+* Engine Base Class *
+*************************************************/
+class BOTAN_DLL Engine
+ {
+ public:
+ template<typename T>
+ class BOTAN_DLL Algorithm_Cache
+ {
+ public:
+ virtual T* get(const std::string&) const = 0;
+ virtual void add(T* algo, const std::string& = "") const = 0;
+ virtual ~Algorithm_Cache() {}
+ };
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ virtual NR_Operation* nr_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ virtual ECDSA_Operation* ecdsa_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ virtual ECKAEG_Operation* eckaeg_op(const EC_Domain_Params&,
+ const BigInt&,
+ const PointGFp&) const
+ { return 0; }
+#endif
+
+ virtual Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const
+ { return 0; }
+
+ virtual Keyed_Filter* get_cipher(const std::string&, Cipher_Dir)
+ { return 0; }
+
+ const BlockCipher* block_cipher(const std::string&) const;
+ const StreamCipher* stream_cipher(const std::string&) const;
+ const HashFunction* hash(const std::string&) const;
+ const MessageAuthenticationCode* mac(const std::string&) const;
+ const class S2K* s2k(const std::string&) const;
+ const class BlockCipherModePaddingMethod*
+ bc_pad(const std::string&) const;
+
+ virtual bool can_add_algorithms() { return false; }
+
+ void add_algorithm(BlockCipher*) const;
+ void add_algorithm(StreamCipher*) const;
+ void add_algorithm(HashFunction*) const;
+ void add_algorithm(MessageAuthenticationCode*) const;
+ void add_algorithm(class S2K*) const;
+ void add_algorithm(class BlockCipherModePaddingMethod*) const;
+
+ Engine();
+ virtual ~Engine();
+ private:
+ virtual BlockCipher* find_block_cipher(const std::string&) const
+ { return 0; }
+ virtual StreamCipher* find_stream_cipher(const std::string&) const
+ { return 0; }
+
+ virtual HashFunction* find_hash(const std::string&) const
+ { return 0; }
+
+ virtual MessageAuthenticationCode* find_mac(const std::string&) const
+ { return 0; }
+
+ virtual class S2K* find_s2k(const std::string&) const
+ { return 0; }
+
+ virtual class BlockCipherModePaddingMethod*
+ find_bc_pad(const std::string&) const
+ { return 0; }
+
+ template<typename T>
+ const T* lookup_algo(const Algorithm_Cache<T>* cache,
+ const std::string& name,
+ const Engine* engine,
+ T* (Engine::*find)(const std::string&) const) const
+ {
+ T* algo = cache->get(name);
+ if(!algo)
+ {
+ algo = (engine->*find)(name);
+ if(algo)
+ cache->add(algo, name);
+ }
+ return algo;
+ }
+
+ Algorithm_Cache<BlockCipher>* cache_of_bc;
+ Algorithm_Cache<StreamCipher>* cache_of_sc;
+ Algorithm_Cache<HashFunction>* cache_of_hf;
+ Algorithm_Cache<MessageAuthenticationCode>* cache_of_mac;
+ Algorithm_Cache<BlockCipherModePaddingMethod>* cache_of_bc_pad;
+ Algorithm_Cache<S2K>* cache_of_s2k;
+ };
+
+namespace Engine_Core {
+
+/*************************************************
+* Get an operation from an Engine *
+*************************************************/
+Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints);
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+DH_Operation* dh_op(const DL_Group&, const BigInt&);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ECDSA_Operation* ecdsa_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+#if defined(BOTAN_HAS_ECKAEG)
+ECKAEG_Operation* eckaeg_op(const EC_Domain_Params& dom_pars,
+ const BigInt& priv_key,
+ const PointGFp& pub_key);
+#endif
+
+}
+
+}
+
+#endif
diff --git a/src/libstate/engine/gnump/eng_gmp.h b/src/libstate/engine/gnump/eng_gmp.h
new file mode 100644
index 000000000..a0ff2661c
--- /dev/null
+++ b/src/libstate/engine/gnump/eng_gmp.h
@@ -0,0 +1,53 @@
+/*************************************************
+* GMP Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ENGINE_GMP_H__
+#define BOTAN_ENGINE_GMP_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*************************************************
+* GMP Engine *
+*************************************************/
+class BOTAN_DLL GMP_Engine : public Engine
+ {
+ public:
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+
+ GMP_Engine();
+ private:
+ static void set_memory_hooks();
+ };
+
+}
+
+#endif
diff --git a/src/libstate/engine/gnump/gmp_dh.cpp b/src/libstate/engine/gnump/gmp_dh.cpp
new file mode 100644
index 000000000..ef2732626
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_dh.cpp
@@ -0,0 +1,51 @@
+/*************************************************
+* GMP Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+namespace {
+
+/*************************************************
+* GMP DH Operation *
+*************************************************/
+class GMP_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new GMP_DH_Op(*this); }
+
+ GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, p;
+ };
+
+/*************************************************
+* GMP DH Key Agreement Operation *
+*************************************************/
+BigInt GMP_DH_Op::agree(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, x.value, p.value);
+ return i.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const
+ {
+ return new GMP_DH_Op(group, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/gnump/gmp_dsa.cpp b/src/libstate/engine/gnump/gmp_dsa.cpp
new file mode 100644
index 000000000..209c6e0a6
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_dsa.cpp
@@ -0,0 +1,122 @@
+/*************************************************
+* GMP DSA Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DSA)
+
+namespace {
+
+/*************************************************
+* GMP DSA Operation *
+*************************************************/
+class GMP_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new GMP_DSA_Op(*this); }
+
+ GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*************************************************
+* GMP DSA Verify Operation *
+*************************************************/
+bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ GMP_MPZ r(sig, q_bytes);
+ GMP_MPZ s(sig + q_bytes, q_bytes);
+ GMP_MPZ i(msg, msg_len);
+
+ if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0)
+ return false;
+ if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(mpz_invert(s.value, s.value, q.value) == 0)
+ return false;
+
+ GMP_MPZ si;
+ mpz_mul(si.value, s.value, i.value);
+ mpz_mod(si.value, si.value, q.value);
+ mpz_powm(si.value, g.value, si.value, p.value);
+
+ GMP_MPZ sr;
+ mpz_mul(sr.value, s.value, r.value);
+ mpz_mod(sr.value, sr.value, q.value);
+ mpz_powm(sr.value, y.value, sr.value, p.value);
+
+ mpz_mul(si.value, si.value, sr.value);
+ mpz_mod(si.value, si.value, p.value);
+ mpz_mod(si.value, si.value, q.value);
+
+ if(mpz_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*************************************************
+* GMP DSA Sign Operation *
+*************************************************/
+SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: No private key");
+
+ GMP_MPZ i(in, length);
+ GMP_MPZ k(k_bn);
+
+ GMP_MPZ r;
+ mpz_powm(r.value, g.value, k.value, p.value);
+ mpz_mod(r.value, r.value, q.value);
+
+ mpz_invert(k.value, k.value, q.value);
+
+ GMP_MPZ s;
+ mpz_mul(s.value, x.value, r.value);
+ mpz_add(s.value, s.value, i.value);
+ mpz_mul(s.value, s.value, k.value);
+ mpz_mod(s.value, s.value, q.value);
+
+ if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0)
+ throw Internal_Error("GMP_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_DSA_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/gnump/gmp_elg.cpp b/src/libstate/engine/gnump/gmp_elg.cpp
new file mode 100644
index 000000000..63e9440ff
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_elg.cpp
@@ -0,0 +1,90 @@
+/*************************************************
+* GMP ElGamal Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*************************************************
+* GMP ElGamal Operation *
+*************************************************/
+class GMP_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new GMP_ELG_Op(*this); }
+
+ GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ GMP_MPZ x, y, g, p;
+ };
+
+/*************************************************
+* GMP ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ GMP_MPZ i(in, length);
+
+ if(mpz_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Input is too large");
+
+ GMP_MPZ a, b, k(k_bn);
+
+ mpz_powm(a.value, g.value, k.value, p.value);
+ mpz_powm(b.value, y.value, k.value, p.value);
+ mpz_mul(b.value, b.value, i.value);
+ mpz_mod(b.value, b.value, p.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* GMP ElGamal Decrypt Operation *
+*************************************************/
+BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_ELG_Op::decrypt: No private key");
+
+ GMP_MPZ a(a_bn), b(b_bn);
+
+ if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("GMP_ELG_Op: Invalid message");
+
+ mpz_powm(a.value, a.value, x.value, p.value);
+ mpz_invert(a.value, a.value, p.value);
+ mpz_mul(a.value, a.value, b.value);
+ mpz_mod(a.value, a.value, p.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_ELG_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/gnump/gmp_if.cpp b/src/libstate/engine/gnump/gmp_if.cpp
new file mode 100644
index 000000000..a4a4d0476
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_if.cpp
@@ -0,0 +1,79 @@
+/*************************************************
+* GMP IF Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+
+namespace {
+
+/*************************************************
+* GMP IF Operation *
+*************************************************/
+class GMP_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new GMP_IF_Op(*this); }
+
+ GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const GMP_MPZ e, n, p, q, d1, d2, c;
+ };
+
+/*************************************************
+* GMP IF Public Operation *
+*************************************************/
+BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ GMP_MPZ i(i_bn);
+ mpz_powm(i.value, i.value, e.value, n.value);
+ return i.to_bigint();
+ }
+
+/*************************************************
+* GMP IF Private Operation *
+*************************************************/
+BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(mpz_cmp_ui(p.value, 0) == 0)
+ throw Internal_Error("GMP_IF_Op::private_op: No private key");
+
+ GMP_MPZ j1, j2, h(i_bn);
+
+ mpz_powm(j1.value, h.value, d1.value, p.value);
+ mpz_powm(j2.value, h.value, d2.value, q.value);
+ mpz_sub(h.value, j1.value, j2.value);
+ mpz_mul(h.value, h.value, c.value);
+ mpz_mod(h.value, h.value, p.value);
+ mpz_mul(h.value, h.value, q.value);
+ mpz_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new GMP_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/gnump/gmp_mem.cpp b/src/libstate/engine/gnump/gmp_mem.cpp
new file mode 100644
index 000000000..91ba94dd7
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_mem.cpp
@@ -0,0 +1,68 @@
+/*************************************************
+* GNU MP Memory Handlers Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <cstring>
+#include <gmp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* Allocator used by GNU MP *
+*************************************************/
+Allocator* gmp_alloc = 0;
+
+/*************************************************
+* Allocation Function for GNU MP *
+*************************************************/
+void* gmp_malloc(size_t n)
+ {
+ return gmp_alloc->allocate(n);
+ }
+
+/*************************************************
+* Reallocation Function for GNU MP *
+*************************************************/
+void* gmp_realloc(void* ptr, size_t old_n, size_t new_n)
+ {
+ void* new_buf = gmp_alloc->allocate(new_n);
+ std::memcpy(new_buf, ptr, std::min(old_n, new_n));
+ gmp_alloc->deallocate(ptr, old_n);
+ return new_buf;
+ }
+
+/*************************************************
+* Deallocation Function for GNU MP *
+*************************************************/
+void gmp_free(void* ptr, size_t n)
+ {
+ gmp_alloc->deallocate(ptr, n);
+ }
+
+}
+
+/*************************************************
+* Set the GNU MP memory functions *
+*************************************************/
+void GMP_Engine::set_memory_hooks()
+ {
+ if(gmp_alloc == 0)
+ {
+ gmp_alloc = Allocator::get(true);
+ mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
+ }
+ }
+
+/*************************************************
+* GMP_Engine Constructor *
+*************************************************/
+GMP_Engine::GMP_Engine()
+ {
+ set_memory_hooks();
+ }
+
+}
diff --git a/src/libstate/engine/gnump/gmp_nr.cpp b/src/libstate/engine/gnump/gmp_nr.cpp
new file mode 100644
index 000000000..97b7e5554
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_nr.cpp
@@ -0,0 +1,105 @@
+/*************************************************
+* GMP NR Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+#include <gmp.h>
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+
+namespace {
+
+/*************************************************
+* GMP NR Operation *
+*************************************************/
+class GMP_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new GMP_NR_Op(*this); }
+
+ GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const GMP_MPZ x, y, p, q, g;
+ };
+
+/*************************************************
+* GMP NR Verify Operation *
+*************************************************/
+SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ GMP_MPZ c(sig, q_bytes);
+ GMP_MPZ d(sig + q_bytes, q_bytes);
+
+ if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 ||
+ mpz_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature");
+
+ GMP_MPZ i1, i2;
+ mpz_powm(i1.value, g.value, d.value, p.value);
+ mpz_powm(i2.value, y.value, c.value, p.value);
+ mpz_mul(i1.value, i1.value, i2.value);
+ mpz_mod(i1.value, i1.value, p.value);
+ mpz_sub(i1.value, c.value, i1.value);
+ mpz_mod(i1.value, i1.value, q.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*************************************************
+* GMP NR Sign Operation *
+*************************************************/
+SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(mpz_cmp_ui(x.value, 0) == 0)
+ throw Internal_Error("GMP_NR_Op::sign: No private key");
+
+ GMP_MPZ f(in, length);
+ GMP_MPZ k(k_bn);
+
+ if(mpz_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range");
+
+ GMP_MPZ c, d;
+ mpz_powm(c.value, g.value, k.value, p.value);
+ mpz_add(c.value, c.value, f.value);
+ mpz_mod(c.value, c.value, q.value);
+ mpz_mul(d.value, x.value, c.value);
+ mpz_sub(d.value, k.value, d.value);
+ mpz_mod(d.value, d.value, q.value);
+
+ if(mpz_cmp_ui(c.value, 0) == 0)
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new GMP_NR_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/gnump/gmp_powm.cpp b/src/libstate/engine/gnump/gmp_powm.cpp
new file mode 100644
index 000000000..a5e3d1c0d
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_powm.cpp
@@ -0,0 +1,51 @@
+/*************************************************
+* GMP Modular Exponentiation Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_gmp.h>
+#include <botan/gmp_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* GMP Modular Exponentiator *
+*************************************************/
+class GMP_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new GMP_Modular_Exponentiator(*this); }
+
+ GMP_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ GMP_MPZ base, exp, mod;
+ };
+
+/*************************************************
+* Compute the result *
+*************************************************/
+BigInt GMP_Modular_Exponentiator::execute() const
+ {
+ GMP_MPZ r;
+ mpz_powm(r.value, base.value, exp.value, mod.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Return the GMP-based modular exponentiator *
+*************************************************/
+Modular_Exponentiator* GMP_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new GMP_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/src/libstate/engine/gnump/gmp_wrap.cpp b/src/libstate/engine/gnump/gmp_wrap.cpp
new file mode 100644
index 000000000..4c73c2562
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_wrap.cpp
@@ -0,0 +1,96 @@
+/*************************************************
+* GMP Wrapper Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/gmp_wrap.h>
+
+#define GNU_MP_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
+
+#define GNU_MP_VERSION_CODE \
+ GNU_MP_VERSION_CODE_FOR(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, \
+ __GNU_MP_VERSION_PATCHLEVEL)
+
+#if GNU_MP_VERSION_CODE < GNU_MP_VERSION_CODE_FOR(4,1,0)
+ #error Your GNU MP install is too old, upgrade to 4.1 or later
+#endif
+
+namespace Botan {
+
+/*************************************************
+* GMP_MPZ Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const BigInt& in)
+ {
+ mpz_init(value);
+ if(in != 0)
+ mpz_import(value, in.sig_words(), -1, sizeof(word), 0, 0, in.data());
+ }
+
+/*************************************************
+* GMP_MPZ Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const byte in[], u32bit length)
+ {
+ mpz_init(value);
+ mpz_import(value, length, 1, 1, 0, 0, in);
+ }
+
+/*************************************************
+* GMP_MPZ Copy Constructor *
+*************************************************/
+GMP_MPZ::GMP_MPZ(const GMP_MPZ& other)
+ {
+ mpz_init_set(value, other.value);
+ }
+
+/*************************************************
+* GMP_MPZ Destructor *
+*************************************************/
+GMP_MPZ::~GMP_MPZ()
+ {
+ mpz_clear(value);
+ }
+
+/*************************************************
+* GMP_MPZ Assignment Operator *
+*************************************************/
+GMP_MPZ& GMP_MPZ::operator=(const GMP_MPZ& other)
+ {
+ mpz_set(value, other.value);
+ return (*this);
+ }
+
+/*************************************************
+* Export the mpz_t as a bytestring *
+*************************************************/
+void GMP_MPZ::encode(byte out[], u32bit length) const
+ {
+ size_t dummy = 0;
+ mpz_export(out + (length - bytes()), &dummy, 1, 1, 0, 0, value);
+ }
+
+/*************************************************
+* Return the number of significant bytes *
+*************************************************/
+u32bit GMP_MPZ::bytes() const
+ {
+ return ((mpz_sizeinbase(value, 2) + 7) / 8);
+ }
+
+/*************************************************
+* GMP to BigInt Conversions *
+*************************************************/
+BigInt GMP_MPZ::to_bigint() const
+ {
+ BigInt out(BigInt::Positive, (bytes() + sizeof(word) - 1) / sizeof(word));
+ size_t dummy = 0;
+ mpz_export(out.get_reg(), &dummy, -1, sizeof(word), 0, 0, value);
+
+ if(mpz_sgn(value) < 0)
+ out.flip_sign();
+
+ return out;
+ }
+
+}
diff --git a/src/libstate/engine/gnump/gmp_wrap.h b/src/libstate/engine/gnump/gmp_wrap.h
new file mode 100644
index 000000000..e2a420e6b
--- /dev/null
+++ b/src/libstate/engine/gnump/gmp_wrap.h
@@ -0,0 +1,36 @@
+/*************************************************
+* GMP MPZ Wrapper Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_GMP_MPZ_WRAP_H__
+#define BOTAN_GMP_MPZ_WRAP_H__
+
+#include <botan/bigint.h>
+#include <gmp.h>
+
+namespace Botan {
+
+/*************************************************
+* Lightweight GMP mpz_t Wrapper *
+*************************************************/
+class BOTAN_DLL GMP_MPZ
+ {
+ public:
+ mpz_t value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ GMP_MPZ& operator=(const GMP_MPZ&);
+
+ GMP_MPZ(const GMP_MPZ&);
+ GMP_MPZ(const BigInt& = 0);
+ GMP_MPZ(const byte[], u32bit);
+ ~GMP_MPZ();
+ };
+
+}
+
+#endif
diff --git a/src/libstate/engine/gnump/info.txt b/src/libstate/engine/gnump/info.txt
new file mode 100644
index 000000000..33fa720f5
--- /dev/null
+++ b/src/libstate/engine/gnump/info.txt
@@ -0,0 +1,26 @@
+realname "GMP Engine"
+
+define ENGINE_GNU_MP
+
+load_on request
+
+<libs>
+all -> gmp
+</libs>
+
+<requires>
+libstate
+</requires>
+
+<add>
+eng_gmp.h
+gmp_dh.cpp
+gmp_dsa.cpp
+gmp_elg.cpp
+gmp_if.cpp
+gmp_mem.cpp
+gmp_nr.cpp
+gmp_powm.cpp
+gmp_wrap.cpp
+gmp_wrap.h
+</add>
diff --git a/src/libstate/engine/info.txt b/src/libstate/engine/info.txt
new file mode 100644
index 000000000..be82273f4
--- /dev/null
+++ b/src/libstate/engine/info.txt
@@ -0,0 +1,10 @@
+realname "Engines"
+
+define ENGINES
+
+load_on auto
+
+<add>
+engine.cpp
+engine.h
+</add>
diff --git a/src/libstate/engine/openssl/bn_powm.cpp b/src/libstate/engine/openssl/bn_powm.cpp
new file mode 100644
index 000000000..f54411240
--- /dev/null
+++ b/src/libstate/engine/openssl/bn_powm.cpp
@@ -0,0 +1,52 @@
+/*************************************************
+* OpenSSL Modular Exponentiation Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OpenSSL Modular Exponentiator *
+*************************************************/
+class OpenSSL_Modular_Exponentiator : public Modular_Exponentiator
+ {
+ public:
+ void set_base(const BigInt& b) { base = b; }
+ void set_exponent(const BigInt& e) { exp = e; }
+ BigInt execute() const;
+ Modular_Exponentiator* copy() const
+ { return new OpenSSL_Modular_Exponentiator(*this); }
+
+ OpenSSL_Modular_Exponentiator(const BigInt& n) : mod(n) {}
+ private:
+ OSSL_BN base, exp, mod;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* Compute the result *
+*************************************************/
+BigInt OpenSSL_Modular_Exponentiator::execute() const
+ {
+ OSSL_BN r;
+ BN_mod_exp(r.value, base.value, exp.value, mod.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Return the OpenSSL-based modular exponentiator *
+*************************************************/
+Modular_Exponentiator* OpenSSL_Engine::mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const
+ {
+ return new OpenSSL_Modular_Exponentiator(n);
+ }
+
+}
diff --git a/src/libstate/engine/openssl/bn_wrap.cpp b/src/libstate/engine/openssl/bn_wrap.cpp
new file mode 100644
index 000000000..4f7ea0078
--- /dev/null
+++ b/src/libstate/engine/openssl/bn_wrap.cpp
@@ -0,0 +1,114 @@
+/*************************************************
+* OpenSSL BN Wrapper Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/bn_wrap.h>
+
+namespace Botan {
+
+/*************************************************
+* OSSL_BN Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const BigInt& in)
+ {
+ value = BN_new();
+ SecureVector<byte> encoding = BigInt::encode(in);
+ if(in != 0)
+ BN_bin2bn(encoding, encoding.size(), value);
+ }
+
+/*************************************************
+* OSSL_BN Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const byte in[], u32bit length)
+ {
+ value = BN_new();
+ BN_bin2bn(in, length, value);
+ }
+
+/*************************************************
+* OSSL_BN Copy Constructor *
+*************************************************/
+OSSL_BN::OSSL_BN(const OSSL_BN& other)
+ {
+ value = BN_dup(other.value);
+ }
+
+/*************************************************
+* OSSL_BN Destructor *
+*************************************************/
+OSSL_BN::~OSSL_BN()
+ {
+ BN_clear_free(value);
+ }
+
+/*************************************************
+* OSSL_BN Assignment Operator *
+*************************************************/
+OSSL_BN& OSSL_BN::operator=(const OSSL_BN& other)
+ {
+ BN_copy(value, other.value);
+ return (*this);
+ }
+
+/*************************************************
+* Export the BIGNUM as a bytestring *
+*************************************************/
+void OSSL_BN::encode(byte out[], u32bit length) const
+ {
+ BN_bn2bin(value, out + (length - bytes()));
+ }
+
+/*************************************************
+* Return the number of significant bytes *
+*************************************************/
+u32bit OSSL_BN::bytes() const
+ {
+ return BN_num_bytes(value);
+ }
+
+/*************************************************
+* OpenSSL to BigInt Conversions *
+*************************************************/
+BigInt OSSL_BN::to_bigint() const
+ {
+ SecureVector<byte> out(bytes());
+ BN_bn2bin(value, out);
+ return BigInt::decode(out);
+ }
+
+/*************************************************
+* OSSL_BN_CTX Constructor *
+*************************************************/
+OSSL_BN_CTX::OSSL_BN_CTX()
+ {
+ value = BN_CTX_new();
+ }
+
+/*************************************************
+* OSSL_BN_CTX Copy Constructor *
+*************************************************/
+OSSL_BN_CTX::OSSL_BN_CTX(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ }
+
+/*************************************************
+* OSSL_BN_CTX Destructor *
+*************************************************/
+OSSL_BN_CTX::~OSSL_BN_CTX()
+ {
+ BN_CTX_free(value);
+ }
+
+/*************************************************
+* OSSL_BN_CTX Assignment Operator *
+*************************************************/
+OSSL_BN_CTX& OSSL_BN_CTX::operator=(const OSSL_BN_CTX&)
+ {
+ value = BN_CTX_new();
+ return (*this);
+ }
+
+}
diff --git a/src/libstate/engine/openssl/bn_wrap.h b/src/libstate/engine/openssl/bn_wrap.h
new file mode 100644
index 000000000..e8464e74e
--- /dev/null
+++ b/src/libstate/engine/openssl/bn_wrap.h
@@ -0,0 +1,51 @@
+/*************************************************
+* OpenSSL BN Wrapper Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_OPENSSL_BN_WRAP_H__
+#define BOTAN_OPENSSL_BN_WRAP_H__
+
+#include <botan/bigint.h>
+#include <openssl/bn.h>
+
+namespace Botan {
+
+/*************************************************
+* Lightweight OpenSSL BN Wrapper *
+*************************************************/
+class BOTAN_DLL OSSL_BN
+ {
+ public:
+ BIGNUM* value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], u32bit) const;
+ u32bit bytes() const;
+
+ OSSL_BN& operator=(const OSSL_BN&);
+
+ OSSL_BN(const OSSL_BN&);
+ OSSL_BN(const BigInt& = 0);
+ OSSL_BN(const byte[], u32bit);
+ ~OSSL_BN();
+ };
+
+/*************************************************
+* Lightweight OpenSSL BN_CTX Wrapper *
+*************************************************/
+class BOTAN_DLL OSSL_BN_CTX
+ {
+ public:
+ BN_CTX* value;
+
+ OSSL_BN_CTX& operator=(const OSSL_BN_CTX&);
+
+ OSSL_BN_CTX();
+ OSSL_BN_CTX(const OSSL_BN_CTX&);
+ ~OSSL_BN_CTX();
+ };
+
+}
+
+#endif
diff --git a/src/libstate/engine/openssl/eng_ossl.h b/src/libstate/engine/openssl/eng_ossl.h
new file mode 100644
index 000000000..c63179459
--- /dev/null
+++ b/src/libstate/engine/openssl/eng_ossl.h
@@ -0,0 +1,53 @@
+/*************************************************
+* OpenSSL Engine Header File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ENGINE_OPENSSL_H__
+#define BOTAN_ENGINE_OPENSSL_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/*************************************************
+* OpenSSL Engine *
+*************************************************/
+class BOTAN_DLL OpenSSL_Engine : public Engine
+ {
+ public:
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+ IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&, const BigInt&,
+ const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ DSA_Operation* dsa_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ ELG_Operation* elg_op(const DL_Group&, const BigInt&,
+ const BigInt&) const;
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ DH_Operation* dh_op(const DL_Group&, const BigInt&) const;
+#endif
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const;
+ private:
+ BlockCipher* find_block_cipher(const std::string&) const;
+ StreamCipher* find_stream_cipher(const std::string&) const;
+ HashFunction* find_hash(const std::string&) const;
+ };
+
+}
+
+#endif
diff --git a/src/libstate/engine/openssl/info.txt b/src/libstate/engine/openssl/info.txt
new file mode 100644
index 000000000..0f14ccc7d
--- /dev/null
+++ b/src/libstate/engine/openssl/info.txt
@@ -0,0 +1,28 @@
+realname "OpenSSL Engine"
+
+define ENGINE_OPENSSL
+
+load_on request
+
+<libs>
+all -> crypto
+</libs>
+
+<requires>
+libstate
+</requires>
+
+<add>
+bn_powm.cpp
+bn_wrap.cpp
+bn_wrap.h
+eng_ossl.h
+ossl_bc.cpp
+ossl_dh.cpp
+ossl_dsa.cpp
+ossl_elg.cpp
+ossl_if.cpp
+ossl_md.cpp
+ossl_nr.cpp
+ossl_rc4.cpp
+</add>
diff --git a/src/libstate/engine/openssl/ossl_bc.cpp b/src/libstate/engine/openssl/ossl_bc.cpp
new file mode 100644
index 000000000..1863ad477
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_bc.cpp
@@ -0,0 +1,204 @@
+/*************************************************
+* OpenSSL Block Cipher Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* EVP Block Cipher *
+*************************************************/
+class EVP_BlockCipher : public BlockCipher
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return cipher_name; }
+ BlockCipher* clone() const;
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&);
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&,
+ u32bit, u32bit, u32bit);
+
+ ~EVP_BlockCipher();
+ private:
+ void enc(const byte[], byte[]) const;
+ void dec(const byte[], byte[]) const;
+ void key_schedule(const byte[], u32bit);
+ std::string cipher_name;
+ mutable EVP_CIPHER_CTX encrypt, decrypt;
+ };
+
+/*************************************************
+* EVP Block Cipher Constructor *
+*************************************************/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name) :
+ BlockCipher(EVP_CIPHER_block_size(algo), EVP_CIPHER_key_length(algo)),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*************************************************
+* EVP Block Cipher Constructor *
+*************************************************/
+EVP_BlockCipher::EVP_BlockCipher(const EVP_CIPHER* algo,
+ const std::string& algo_name,
+ u32bit key_min, u32bit key_max,
+ u32bit key_mod) :
+ BlockCipher(EVP_CIPHER_block_size(algo), key_min, key_max, key_mod),
+ cipher_name(algo_name)
+ {
+ if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE)
+ throw Invalid_Argument("EVP_BlockCipher: Non-ECB EVP was passed in");
+
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+/*************************************************
+* EVP Block Cipher Destructor *
+*************************************************/
+EVP_BlockCipher::~EVP_BlockCipher()
+ {
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ }
+
+/*************************************************
+* Encrypt a block *
+*************************************************/
+void EVP_BlockCipher::enc(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_EncryptUpdate(&encrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*************************************************
+* Decrypt a block *
+*************************************************/
+void EVP_BlockCipher::dec(const byte in[], byte out[]) const
+ {
+ int out_len = 0;
+ EVP_DecryptUpdate(&decrypt, out, &out_len, in, BLOCK_SIZE);
+ }
+
+/*************************************************
+* Set the key *
+*************************************************/
+void EVP_BlockCipher::key_schedule(const byte key[], u32bit length)
+ {
+ SecureVector<byte> full_key(key, length);
+
+ if(cipher_name == "TripleDES" && length == 16)
+ full_key.append(key, 8);
+ else
+ if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 ||
+ EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0)
+ throw Invalid_Argument("EVP_BlockCipher: Bad key length for " +
+ cipher_name);
+
+ if(cipher_name == "RC2")
+ {
+ EVP_CIPHER_CTX_ctrl(&encrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ EVP_CIPHER_CTX_ctrl(&decrypt, EVP_CTRL_SET_RC2_KEY_BITS, length*8, 0);
+ }
+
+ EVP_EncryptInit_ex(&encrypt, 0, 0, full_key.begin(), 0);
+ EVP_DecryptInit_ex(&decrypt, 0, 0, full_key.begin(), 0);
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+BlockCipher* EVP_BlockCipher::clone() const
+ {
+ return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
+ cipher_name, MINIMUM_KEYLENGTH,
+ MAXIMUM_KEYLENGTH, KEYLENGTH_MULTIPLE);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void EVP_BlockCipher::clear() throw()
+ {
+ const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt);
+
+ EVP_CIPHER_CTX_cleanup(&encrypt);
+ EVP_CIPHER_CTX_cleanup(&decrypt);
+ EVP_CIPHER_CTX_init(&encrypt);
+ EVP_CIPHER_CTX_init(&decrypt);
+ EVP_EncryptInit_ex(&encrypt, algo, 0, 0, 0);
+ EVP_DecryptInit_ex(&decrypt, algo, 0, 0, 0);
+ EVP_CIPHER_CTX_set_padding(&encrypt, 0);
+ EVP_CIPHER_CTX_set_padding(&decrypt, 0);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+BlockCipher*
+OpenSSL_Engine::find_block_cipher(const std::string& algo_spec) const
+ {
+#define HANDLE_EVP_CIPHER(NAME, EVP) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_BlockCipher(EVP, NAME); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+ HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1);
+ HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8);
+ HANDLE_EVP_CIPHER("DES", EVP_des_ecb());
+ HANDLE_EVP_CIPHER("AES-128", EVP_aes_128_ecb());
+ HANDLE_EVP_CIPHER("AES-192", EVP_aes_192_ecb());
+ HANDLE_EVP_CIPHER("AES-256", EVP_aes_256_ecb());
+
+#undef HANDLE_EVP_CIPHER
+#undef HANDLE_EVP_CIPHER_KEYLEN
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/openssl/ossl_dh.cpp b/src/libstate/engine/openssl/ossl_dh.cpp
new file mode 100644
index 000000000..290b95622
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_dh.cpp
@@ -0,0 +1,58 @@
+/*************************************************
+* OpenSSL Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+
+namespace {
+
+/*************************************************
+* OpenSSL DH Operation *
+*************************************************/
+class OpenSSL_DH_Op : public DH_Operation
+ {
+ public:
+ BigInt agree(const BigInt& i) const;
+ DH_Operation* clone() const { return new OpenSSL_DH_Op(*this); }
+
+ OpenSSL_DH_Op(const DL_Group& group, const BigInt& x_bn) :
+ x(x_bn), p(group.get_p()) {}
+ private:
+ OSSL_BN x, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL DH Key Agreement Operation *
+*************************************************/
+BigInt OpenSSL_DH_Op::agree(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value);
+ return r.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire a DH op *
+*************************************************/
+DH_Operation* OpenSSL_Engine::dh_op(const DL_Group& group,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DH_Op(group, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/openssl/ossl_dsa.cpp b/src/libstate/engine/openssl/ossl_dsa.cpp
new file mode 100644
index 000000000..2757234e2
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_dsa.cpp
@@ -0,0 +1,124 @@
+/*************************************************
+* OpenSSL DSA Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_DSA)
+
+namespace {
+
+/*************************************************
+* OpenSSL DSA Operation *
+*************************************************/
+class OpenSSL_DSA_Op : public DSA_Operation
+ {
+ public:
+ bool verify(const byte[], u32bit, const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ DSA_Operation* clone() const { return new OpenSSL_DSA_Op(*this); }
+
+ OpenSSL_DSA_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL DSA Verify Operation *
+*************************************************/
+bool OpenSSL_DSA_Op::verify(const byte msg[], u32bit msg_len,
+ const byte sig[], u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes || msg_len > q_bytes)
+ return false;
+
+ OSSL_BN r(sig, q_bytes);
+ OSSL_BN s(sig + q_bytes, q_bytes);
+ OSSL_BN i(msg, msg_len);
+
+ if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0)
+ return false;
+ if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0)
+ return false;
+
+ if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0)
+ return false;
+
+ OSSL_BN si;
+ BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value);
+ BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value);
+
+ OSSL_BN sr;
+ BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value);
+ BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value);
+
+ BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value);
+ BN_nnmod(si.value, si.value, q.value, ctx.value);
+
+ if(BN_cmp(si.value, r.value) == 0)
+ return true;
+ return false;
+ }
+
+/*************************************************
+* OpenSSL DSA Sign Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_DSA_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: No private key");
+
+ OSSL_BN i(in, length);
+ OSSL_BN k(k_bn);
+
+ OSSL_BN r;
+ BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value);
+ BN_nnmod(r.value, r.value, q.value, ctx.value);
+
+ BN_mod_inverse(k.value, k.value, q.value, ctx.value);
+
+ OSSL_BN s;
+ BN_mul(s.value, x.value, r.value, ctx.value);
+ BN_add(s.value, s.value, i.value);
+ BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value);
+
+ if(BN_is_zero(r.value) || BN_is_zero(s.value))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero");
+
+ const u32bit q_bytes = q.bytes();
+
+ SecureVector<byte> output(2*q_bytes);
+ r.encode(output, q_bytes);
+ s.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a DSA op *
+*************************************************/
+DSA_Operation* OpenSSL_Engine::dsa_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_DSA_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/openssl/ossl_elg.cpp b/src/libstate/engine/openssl/ossl_elg.cpp
new file mode 100644
index 000000000..25d628ba8
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_elg.cpp
@@ -0,0 +1,93 @@
+/*************************************************
+* OpenSSL Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*************************************************
+* OpenSSL ElGamal Operation *
+*************************************************/
+class OpenSSL_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); }
+ OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ OSSL_BN x, y, g, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ OSSL_BN i(in, length);
+
+ if(BN_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large");
+
+ OSSL_BN a, b, k(k_bn);
+
+ BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value);
+ BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value);
+ BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* OpenSSL ElGamal Decrypt Operation *
+*************************************************/
+BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key");
+
+ OSSL_BN a(a_bn), b(b_bn), t;
+
+ if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message");
+
+ BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value);
+ BN_mod_inverse(a.value, t.value, p.value, ctx.value);
+ BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_ELG_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/openssl/ossl_if.cpp b/src/libstate/engine/openssl/ossl_if.cpp
new file mode 100644
index 000000000..08a43e63e
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_if.cpp
@@ -0,0 +1,83 @@
+/*************************************************
+* OpenSSL IF Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY)
+
+namespace {
+
+/*************************************************
+* OpenSSL IF Operation *
+*************************************************/
+class OpenSSL_IF_Op : public IF_Operation
+ {
+ public:
+ BigInt public_op(const BigInt&) const;
+ BigInt private_op(const BigInt&) const;
+
+ IF_Operation* clone() const { return new OpenSSL_IF_Op(*this); }
+
+ OpenSSL_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&,
+ const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn,
+ const BigInt& d2_bn, const BigInt& c_bn) :
+ e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {}
+ private:
+ const OSSL_BN e, n, p, q, d1, d2, c;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL IF Public Operation *
+*************************************************/
+BigInt OpenSSL_IF_Op::public_op(const BigInt& i_bn) const
+ {
+ OSSL_BN i(i_bn), r;
+ BN_mod_exp(r.value, i.value, e.value, n.value, ctx.value);
+ return r.to_bigint();
+ }
+
+/*************************************************
+* OpenSSL IF Private Operation *
+*************************************************/
+BigInt OpenSSL_IF_Op::private_op(const BigInt& i_bn) const
+ {
+ if(BN_is_zero(p.value))
+ throw Internal_Error("OpenSSL_IF_Op::private_op: No private key");
+
+ OSSL_BN j1, j2, h(i_bn);
+
+ BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value);
+ BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value);
+ BN_sub(h.value, j1.value, j2.value);
+ BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value);
+ BN_mul(h.value, h.value, q.value, ctx.value);
+ BN_add(h.value, h.value, j2.value);
+ return h.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an IF op *
+*************************************************/
+IF_Operation* OpenSSL_Engine::if_op(const BigInt& e, const BigInt& n,
+ const BigInt& d, const BigInt& p,
+ const BigInt& q, const BigInt& d1,
+ const BigInt& d2, const BigInt& c) const
+ {
+ return new OpenSSL_IF_Op(e, n, d, p, q, d1, d2, c);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/openssl/ossl_md.cpp b/src/libstate/engine/openssl/ossl_md.cpp
new file mode 100644
index 000000000..8e24c7213
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_md.cpp
@@ -0,0 +1,121 @@
+/*************************************************
+* OpenSSL Hash Functions Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* EVP Hash Function *
+*************************************************/
+class EVP_HashFunction : public HashFunction
+ {
+ public:
+ void clear() throw();
+ std::string name() const { return algo_name; }
+ HashFunction* clone() const;
+ EVP_HashFunction(const EVP_MD*, const std::string&);
+ ~EVP_HashFunction();
+ private:
+ void add_data(const byte[], u32bit);
+ void final_result(byte[]);
+
+ std::string algo_name;
+ EVP_MD_CTX md;
+ };
+
+/*************************************************
+* Update an EVP Hash Calculation *
+*************************************************/
+void EVP_HashFunction::add_data(const byte input[], u32bit length)
+ {
+ EVP_DigestUpdate(&md, input, length);
+ }
+
+/*************************************************
+* Finalize an EVP Hash Calculation *
+*************************************************/
+void EVP_HashFunction::final_result(byte output[])
+ {
+ EVP_DigestFinal_ex(&md, output, 0);
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void EVP_HashFunction::clear() throw()
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Return a clone of this object *
+*************************************************/
+HashFunction* EVP_HashFunction::clone() const
+ {
+ const EVP_MD* algo = EVP_MD_CTX_md(&md);
+ return new EVP_HashFunction(algo, name());
+ }
+
+/*************************************************
+* Create an EVP hash function *
+*************************************************/
+EVP_HashFunction::EVP_HashFunction(const EVP_MD* algo,
+ const std::string& name) :
+ HashFunction(EVP_MD_size(algo), EVP_MD_block_size(algo)),
+ algo_name(name)
+ {
+ EVP_MD_CTX_init(&md);
+ EVP_DigestInit_ex(&md, algo, 0);
+ }
+
+/*************************************************
+* Destroy an EVP hash function *
+*************************************************/
+EVP_HashFunction::~EVP_HashFunction()
+ {
+ EVP_MD_CTX_cleanup(&md);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+HashFunction* OpenSSL_Engine::find_hash(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#define HANDLE_EVP_MD(NAME, EVP) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new EVP_HashFunction(EVP, NAME); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ HANDLE_EVP_MD("SHA-160", EVP_sha1());
+ HANDLE_EVP_MD("MD2", EVP_md2());
+ HANDLE_EVP_MD("MD4", EVP_md4());
+ HANDLE_EVP_MD("MD5", EVP_md5());
+ HANDLE_EVP_MD("RIPEMD-160", EVP_ripemd160());
+
+#undef HANDLE_EVP_MD
+
+ return 0;
+ }
+
+}
diff --git a/src/libstate/engine/openssl/ossl_nr.cpp b/src/libstate/engine/openssl/ossl_nr.cpp
new file mode 100644
index 000000000..210e2fec2
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_nr.cpp
@@ -0,0 +1,111 @@
+/*************************************************
+* OpenSSL NR Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+
+namespace {
+
+/*************************************************
+* OpenSSL NR Operation *
+*************************************************/
+class OpenSSL_NR_Op : public NR_Operation
+ {
+ public:
+ SecureVector<byte> verify(const byte[], u32bit) const;
+ SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const;
+
+ NR_Operation* clone() const { return new OpenSSL_NR_Op(*this); }
+
+ OpenSSL_NR_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {}
+ private:
+ const OSSL_BN x, y, p, q, g;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL NR Verify Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_NR_Op::verify(const byte sig[],
+ u32bit sig_len) const
+ {
+ const u32bit q_bytes = q.bytes();
+
+ if(sig_len != 2*q_bytes)
+ return false;
+
+ OSSL_BN c(sig, q_bytes);
+ OSSL_BN d(sig + q_bytes, q_bytes);
+
+ if(BN_is_zero(c.value) || BN_cmp(c.value, q.value) >= 0 ||
+ BN_cmp(d.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::verify: Invalid signature");
+
+ OSSL_BN i1, i2;
+ BN_mod_exp(i1.value, g.value, d.value, p.value, ctx.value);
+ BN_mod_exp(i2.value, y.value, c.value, p.value, ctx.value);
+ BN_mod_mul(i1.value, i1.value, i2.value, p.value, ctx.value);
+ BN_sub(i1.value, c.value, i1.value);
+ BN_nnmod(i1.value, i1.value, q.value, ctx.value);
+ return BigInt::encode(i1.to_bigint());
+ }
+
+/*************************************************
+* OpenSSL NR Sign Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_NR_Op::sign(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_NR_Op::sign: No private key");
+
+ OSSL_BN f(in, length);
+ OSSL_BN k(k_bn);
+
+ if(BN_cmp(f.value, q.value) >= 0)
+ throw Invalid_Argument("OpenSSL_NR_Op::sign: Input is out of range");
+
+ OSSL_BN c, d;
+ BN_mod_exp(c.value, g.value, k.value, p.value, ctx.value);
+ BN_add(c.value, c.value, f.value);
+ BN_nnmod(c.value, c.value, q.value, ctx.value);
+ BN_mul(d.value, x.value, c.value, ctx.value);
+ BN_sub(d.value, k.value, d.value);
+ BN_nnmod(d.value, d.value, q.value, ctx.value);
+
+ if(BN_is_zero(c.value))
+ throw Internal_Error("Default_NR_Op::sign: c was zero");
+
+ const u32bit q_bytes = q.bytes();
+ SecureVector<byte> output(2*q_bytes);
+ c.encode(output, q_bytes);
+ d.encode(output + q_bytes, q_bytes);
+ return output;
+ }
+
+}
+
+/*************************************************
+* Acquire a NR op *
+*************************************************/
+NR_Operation* OpenSSL_Engine::nr_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_NR_Op(group, y, x);
+ }
+#endif
+
+}
diff --git a/src/libstate/engine/openssl/ossl_rc4.cpp b/src/libstate/engine/openssl/ossl_rc4.cpp
new file mode 100644
index 000000000..ed5c9714f
--- /dev/null
+++ b/src/libstate/engine/openssl/ossl_rc4.cpp
@@ -0,0 +1,92 @@
+/*************************************************
+* OpenSSL ARC4 Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/parsing.h>
+#include <botan/libstate.h>
+#include <openssl/rc4.h>
+
+namespace Botan {
+
+namespace {
+
+/*************************************************
+* OpenSSL ARC4 *
+*************************************************/
+class OpenSSL_ARC4 : public StreamCipher
+ {
+ public:
+ void clear() throw() { std::memset(&state, 0, sizeof(state)); }
+ std::string name() const;
+ StreamCipher* clone() const { return new OpenSSL_ARC4(SKIP); }
+ OpenSSL_ARC4(u32bit s = 0) : StreamCipher(1, 32), SKIP(s) { clear(); }
+ ~OpenSSL_ARC4() { clear(); }
+ private:
+ void cipher(const byte[], byte[], u32bit);
+ void key_schedule(const byte[], u32bit);
+
+ const u32bit SKIP;
+ RC4_KEY state;
+ };
+
+/*************************************************
+* Return the name of this type *
+*************************************************/
+std::string OpenSSL_ARC4::name() const
+ {
+ if(SKIP == 0) return "ARC4";
+ if(SKIP == 256) return "MARK-4";
+ else return "RC4_skip(" + to_string(SKIP) + ")";
+ }
+
+/*************************************************
+* ARC4 Key Schedule *
+*************************************************/
+void OpenSSL_ARC4::key_schedule(const byte key[], u32bit length)
+ {
+ RC4_set_key(&state, length, key);
+ byte dummy = 0;
+ for(u32bit j = 0; j != SKIP; j++)
+ RC4(&state, 1, &dummy, &dummy);
+ }
+
+/*************************************************
+* ARC4 Encryption *
+*************************************************/
+void OpenSSL_ARC4::cipher(const byte in[], byte out[], u32bit length)
+ {
+ RC4(&state, length, in, out);
+ }
+
+}
+
+/*************************************************
+* Look for an algorithm with this name *
+*************************************************/
+StreamCipher*
+OpenSSL_Engine::find_stream_cipher(const std::string& algo_spec) const
+ {
+ std::vector<std::string> name = parse_algorithm_name(algo_spec);
+ if(name.size() == 0)
+ return 0;
+ const std::string algo_name = global_state().deref_alias(name[0]);
+
+#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \
+ if(algo_name == NAME) \
+ { \
+ if(name.size() == 1) \
+ return new TYPE(DEFAULT); \
+ if(name.size() == 2) \
+ return new TYPE(to_u32bit(name[1])); \
+ throw Invalid_Algorithm_Name(algo_spec); \
+ }
+
+ HANDLE_TYPE_ONE_U32BIT("ARC4", OpenSSL_ARC4, 0);
+ HANDLE_TYPE_ONE_U32BIT("RC4_drop", OpenSSL_ARC4, 768);
+
+ return 0;
+ }
+
+}