aboutsummaryrefslogtreecommitdiffstats
path: root/lib/engine
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-01 21:20:55 +0000
committerlloyd <[email protected]>2014-01-01 21:20:55 +0000
commit197dc467dec28a04c3b2f30da7cef122dfbb13e9 (patch)
treecdbd3ddaec051c72f0a757db461973d90c37b97a /lib/engine
parent62faac373c07cfe10bc8c309e89ebdd30d8e5eaa (diff)
Shuffle things around. Add NIST X.509 test to build.
Diffstat (limited to 'lib/engine')
-rw-r--r--lib/engine/aes_isa_eng/aes_isa_engine.cpp36
-rw-r--r--lib/engine/aes_isa_eng/aes_isa_engine.h30
-rw-r--r--lib/engine/aes_isa_eng/info.txt11
-rw-r--r--lib/engine/asm_engine/asm_engine.cpp72
-rw-r--r--lib/engine/asm_engine/asm_engine.h32
-rw-r--r--lib/engine/asm_engine/info.txt11
-rw-r--r--lib/engine/core_engine/core_engine.h71
-rw-r--r--lib/engine/core_engine/core_modes.cpp279
-rw-r--r--lib/engine/core_engine/def_pk_ops.cpp170
-rw-r--r--lib/engine/core_engine/def_powm.cpp24
-rw-r--r--lib/engine/core_engine/info.txt24
-rw-r--r--lib/engine/core_engine/lookup_block.cpp298
-rw-r--r--lib/engine/core_engine/lookup_hash.cpp238
-rw-r--r--lib/engine/core_engine/lookup_mac.cpp70
-rw-r--r--lib/engine/core_engine/lookup_pbkdf.cpp43
-rw-r--r--lib/engine/core_engine/lookup_stream.cpp43
-rw-r--r--lib/engine/dyn_engine/dyn_engine.cpp63
-rw-r--r--lib/engine/dyn_engine/dyn_engine.h115
-rw-r--r--lib/engine/dyn_engine/info.txt14
-rw-r--r--lib/engine/engine.cpp91
-rw-r--r--lib/engine/engine.h150
-rw-r--r--lib/engine/gnump/gmp_mem.cpp83
-rw-r--r--lib/engine/gnump/gmp_powm.cpp53
-rw-r--r--lib/engine/gnump/gmp_wrap.cpp101
-rw-r--r--lib/engine/gnump/gmp_wrap.h41
-rw-r--r--lib/engine/gnump/gnump_engine.h44
-rw-r--r--lib/engine/gnump/gnump_pk.cpp338
-rw-r--r--lib/engine/gnump/info.txt23
-rw-r--r--lib/engine/info.txt20
-rw-r--r--lib/engine/openssl/bn_powm.cpp54
-rw-r--r--lib/engine/openssl/bn_wrap.cpp116
-rw-r--r--lib/engine/openssl/bn_wrap.h60
-rw-r--r--lib/engine/openssl/info.txt25
-rw-r--r--lib/engine/openssl/openssl_engine.h49
-rw-r--r--lib/engine/openssl/ossl_arc4.cpp89
-rw-r--r--lib/engine/openssl/ossl_bc.cpp248
-rw-r--r--lib/engine/openssl/ossl_md.cpp150
-rw-r--r--lib/engine/openssl/ossl_pk.cpp338
-rw-r--r--lib/engine/simd_engine/info.txt15
-rw-r--r--lib/engine/simd_engine/simd_engine.cpp97
-rw-r--r--lib/engine/simd_engine/simd_engine.h32
41 files changed, 3861 insertions, 0 deletions
diff --git a/lib/engine/aes_isa_eng/aes_isa_engine.cpp b/lib/engine/aes_isa_eng/aes_isa_engine.cpp
new file mode 100644
index 000000000..956a1ce38
--- /dev/null
+++ b/lib/engine/aes_isa_eng/aes_isa_engine.cpp
@@ -0,0 +1,36 @@
+/*
+* Engine for AES instructions
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/aes_isa_engine.h>
+#include <botan/cpuid.h>
+
+#if defined(BOTAN_HAS_AES_NI)
+ #include <botan/aes_ni.h>
+#endif
+
+namespace Botan {
+
+BlockCipher*
+AES_ISA_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_AES_NI)
+ if(CPUID::has_aes_ni())
+ {
+ if(request.algo_name() == "AES-128")
+ return new AES_128_NI;
+ if(request.algo_name() == "AES-192")
+ return new AES_192_NI;
+ if(request.algo_name() == "AES-256")
+ return new AES_256_NI;
+ }
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/aes_isa_eng/aes_isa_engine.h b/lib/engine/aes_isa_eng/aes_isa_engine.h
new file mode 100644
index 000000000..3c4d3e936
--- /dev/null
+++ b/lib/engine/aes_isa_eng/aes_isa_engine.h
@@ -0,0 +1,30 @@
+/*
+* Engine for AES instructions
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AES_ISA_ENGINE_H__
+#define BOTAN_AES_ISA_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Engine for implementations that hook into CPU-specific
+* AES implementations (eg AES-NI, VIA C7, or AMD Geode)
+*/
+class AES_ISA_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "aes_isa"; }
+
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/aes_isa_eng/info.txt b/lib/engine/aes_isa_eng/info.txt
new file mode 100644
index 000000000..4284e75bd
--- /dev/null
+++ b/lib/engine/aes_isa_eng/info.txt
@@ -0,0 +1,11 @@
+define ENGINE_AES_ISA 20131128
+
+load_on dep
+
+<source>
+aes_isa_engine.cpp
+</source>
+
+<header:internal>
+aes_isa_engine.h
+</header:internal>
diff --git a/lib/engine/asm_engine/asm_engine.cpp b/lib/engine/asm_engine/asm_engine.cpp
new file mode 100644
index 000000000..a43a3302d
--- /dev/null
+++ b/lib/engine/asm_engine/asm_engine.cpp
@@ -0,0 +1,72 @@
+/*
+* Assembly Implementation Engine
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/asm_engine.h>
+
+#if defined(BOTAN_HAS_SERPENT_X86_32)
+ #include <botan/serp_x86_32.h>
+#endif
+
+#if defined(BOTAN_HAS_MD4_X86_32)
+ #include <botan/md4_x86_32.h>
+#endif
+
+#if defined(BOTAN_HAS_MD5_X86_32)
+ #include <botan/md5_x86_32.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_X86_64)
+ #include <botan/sha1_x86_64.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_X86_32)
+ #include <botan/sha1_x86_32.h>
+#endif
+
+namespace Botan {
+
+BlockCipher*
+Assembler_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+ if(request.algo_name() == "Serpent")
+ {
+#if defined(BOTAN_HAS_SERPENT_X86_32)
+ return new Serpent_X86_32;
+#endif
+ }
+
+ return nullptr;
+ }
+
+HashFunction*
+Assembler_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_MD4_X86_32)
+ if(request.algo_name() == "MD4")
+ return new MD4_X86_32;
+#endif
+
+#if defined(BOTAN_HAS_MD5_X86_32)
+ if(request.algo_name() == "MD5")
+ return new MD5_X86_32;
+#endif
+
+ if(request.algo_name() == "SHA-160")
+ {
+#if defined(BOTAN_HAS_SHA1_X86_64)
+ return new SHA_160_X86_64;
+#elif defined(BOTAN_HAS_SHA1_X86_32)
+ return new SHA_160_X86_32;
+#endif
+ }
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/asm_engine/asm_engine.h b/lib/engine/asm_engine/asm_engine.h
new file mode 100644
index 000000000..40fe5342f
--- /dev/null
+++ b/lib/engine/asm_engine/asm_engine.h
@@ -0,0 +1,32 @@
+/*
+* Assembly Implementation Engine
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_X86_32_ASM_ENGINE_H__
+#define BOTAN_X86_32_ASM_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Engine for x86-32 specific implementations
+*/
+class Assembler_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "asm"; }
+
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/asm_engine/info.txt b/lib/engine/asm_engine/info.txt
new file mode 100644
index 000000000..185656e3d
--- /dev/null
+++ b/lib/engine/asm_engine/info.txt
@@ -0,0 +1,11 @@
+define ENGINE_ASSEMBLER 20131128
+
+load_on dep
+
+<source>
+asm_engine.cpp
+</source>
+
+<header:internal>
+asm_engine.h
+</header:internal>
diff --git a/lib/engine/core_engine/core_engine.h b/lib/engine/core_engine/core_engine.h
new file mode 100644
index 000000000..ca660d21b
--- /dev/null
+++ b/lib/engine/core_engine/core_engine.h
@@ -0,0 +1,71 @@
+/*
+* Core Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CORE_ENGINE_H__
+#define BOTAN_CORE_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Core Engine
+*/
+class Core_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const override { return "core"; }
+
+ PK_Ops::Key_Agreement*
+ get_key_agreement_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Signature*
+ get_signature_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Verification* get_verify_op(const Public_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Encryption* get_encryption_op(const Public_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Decryption* get_decryption_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ Modular_Exponentiator* mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints) const override;
+
+ Keyed_Filter* get_cipher(const std::string&, Cipher_Dir,
+ Algorithm_Factory&);
+
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const override;
+
+ StreamCipher* find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const override;
+
+ HashFunction* find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const override;
+
+ MessageAuthenticationCode* find_mac(const SCAN_Name& request,
+ Algorithm_Factory&) const override;
+
+ PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override;
+ };
+
+/**
+* Create a cipher mode filter object
+* @param block_cipher a block cipher object
+* @param direction are we encrypting or decrypting?
+* @param mode the name of the cipher mode to use
+* @param padding the mode padding to use (only used for ECB, CBC)
+*/
+Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
+ Cipher_Dir direction,
+ const std::string& mode,
+ const std::string& padding);
+
+}
+
+#endif
diff --git a/lib/engine/core_engine/core_modes.cpp b/lib/engine/core_engine/core_modes.cpp
new file mode 100644
index 000000000..6524d9c16
--- /dev/null
+++ b/lib/engine/core_engine/core_modes.cpp
@@ -0,0 +1,279 @@
+/*
+* Core Engine
+* (C) 1999-2007,2011,2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/parsing.h>
+#include <botan/filters.h>
+#include <botan/algo_factory.h>
+#include <botan/mode_pad.h>
+#include <memory>
+
+#if defined(BOTAN_HAS_MODE_CFB)
+ #include <botan/cfb.h>
+#endif
+
+#if defined(BOTAN_HAS_MODE_ECB)
+ #include <botan/ecb.h>
+#endif
+
+#if defined(BOTAN_HAS_MODE_CBC)
+ #include <botan/cbc.h>
+#endif
+
+#if defined(BOTAN_HAS_MODE_XTS)
+ #include <botan/xts.h>
+#endif
+
+#if defined(BOTAN_HAS_OFB)
+ #include <botan/ofb.h>
+#endif
+
+#if defined(BOTAN_HAS_CTR_BE)
+ #include <botan/ctr.h>
+#endif
+
+#if defined(BOTAN_HAS_AEAD_FILTER)
+
+#include <botan/aead_filt.h>
+
+#if defined(BOTAN_HAS_AEAD_CCM)
+ #include <botan/ccm.h>
+#endif
+
+#if defined(BOTAN_HAS_AEAD_EAX)
+ #include <botan/eax.h>
+#endif
+
+#if defined(BOTAN_HAS_AEAD_OCB)
+ #include <botan/ocb.h>
+#endif
+
+#if defined(BOTAN_HAS_AEAD_GCM)
+ #include <botan/gcm.h>
+#endif
+
+#endif
+
+namespace Botan {
+
+namespace {
+
+/**
+* Get a block cipher padding method by name
+*/
+BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec,
+ const std::string& def_if_empty)
+ {
+#if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
+ if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding"))
+ return new Null_Padding;
+
+ if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7"))
+ return new PKCS7_Padding;
+
+ if(algo_spec == "OneAndZeros")
+ return new OneAndZeros_Padding;
+
+ if(algo_spec == "X9.23")
+ return new ANSI_X923_Padding;
+
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+}
+
+Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
+ Cipher_Dir direction,
+ const std::string& mode,
+ const std::string& padding)
+ {
+#if defined(BOTAN_HAS_OFB)
+ if(mode == "OFB")
+ return new StreamCipher_Filter(new OFB(block_cipher->clone()));
+#endif
+
+#if defined(BOTAN_HAS_CTR_BE)
+ if(mode == "CTR-BE")
+ return new StreamCipher_Filter(new CTR_BE(block_cipher->clone()));
+#endif
+
+#if defined(BOTAN_HAS_MODE_ECB)
+ if(mode == "ECB" || mode == "")
+ {
+ if(direction == ENCRYPTION)
+ return new Transformation_Filter(
+ new ECB_Encryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding")));
+ else
+ return new Transformation_Filter(
+ new ECB_Decryption(block_cipher->clone(), get_bc_pad(padding, "NoPadding")));
+ }
+#endif
+
+ if(mode == "CBC")
+ {
+#if defined(BOTAN_HAS_MODE_CBC)
+ if(padding == "CTS")
+ {
+ if(direction == ENCRYPTION)
+ return new Transformation_Filter(new CTS_Encryption(block_cipher->clone()));
+ else
+ return new Transformation_Filter(new CTS_Decryption(block_cipher->clone()));
+ }
+
+ if(direction == ENCRYPTION)
+ return new Transformation_Filter(
+ new CBC_Encryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7")));
+ else
+ return new Transformation_Filter(
+ new CBC_Decryption(block_cipher->clone(), get_bc_pad(padding, "PKCS7")));
+#else
+ return nullptr;
+#endif
+ }
+
+#if defined(BOTAN_HAS_MODE_XTS)
+ if(mode == "XTS")
+ {
+ if(direction == ENCRYPTION)
+ return new Transformation_Filter(new XTS_Encryption(block_cipher->clone()));
+ else
+ return new Transformation_Filter(new XTS_Decryption(block_cipher->clone()));
+ }
+#endif
+
+ if(mode.find("CFB") != std::string::npos ||
+ mode.find("EAX") != std::string::npos ||
+ mode.find("GCM") != std::string::npos ||
+ mode.find("OCB") != std::string::npos ||
+ mode.find("CCM") != std::string::npos)
+ {
+ std::vector<std::string> algo_info = parse_algorithm_name(mode);
+ const std::string mode_name = algo_info[0];
+
+ size_t bits = 8 * block_cipher->block_size();
+ if(algo_info.size() > 1)
+ bits = to_u32bit(algo_info[1]);
+
+#if defined(BOTAN_HAS_MODE_CFB)
+ if(mode_name == "CFB")
+ {
+ if(direction == ENCRYPTION)
+ return new Transformation_Filter(new CFB_Encryption(block_cipher->clone(), bits));
+ else
+ return new Transformation_Filter(new CFB_Decryption(block_cipher->clone(), bits));
+ }
+#endif
+
+#if defined(BOTAN_HAS_AEAD_FILTER)
+
+ if(bits % 8 != 0)
+ throw std::invalid_argument("AEAD interface does not support non-octet length tags");
+
+ const size_t tag_size = bits / 8;
+
+#if defined(BOTAN_HAS_AEAD_CCM)
+ if(mode_name == "CCM")
+ {
+ const size_t L = (algo_info.size() == 3) ? to_u32bit(algo_info[2]) : 3;
+ if(direction == ENCRYPTION)
+ return new AEAD_Filter(new CCM_Encryption(block_cipher->clone(), tag_size, L));
+ else
+ return new AEAD_Filter(new CCM_Decryption(block_cipher->clone(), tag_size, L));
+ }
+#endif
+
+#if defined(BOTAN_HAS_AEAD_EAX)
+ if(mode_name == "EAX")
+ {
+ if(direction == ENCRYPTION)
+ return new AEAD_Filter(new EAX_Encryption(block_cipher->clone(), tag_size));
+ else
+ return new AEAD_Filter(new EAX_Decryption(block_cipher->clone(), tag_size));
+ }
+#endif
+
+#if defined(BOTAN_HAS_AEAD_OCB)
+ if(mode_name == "OCB")
+ {
+ if(direction == ENCRYPTION)
+ return new AEAD_Filter(new OCB_Encryption(block_cipher->clone(), tag_size));
+ else
+ return new AEAD_Filter(new OCB_Decryption(block_cipher->clone(), tag_size));
+ }
+#endif
+
+#if defined(BOTAN_HAS_AEAD_GCM)
+ if(mode_name == "GCM")
+ {
+ if(direction == ENCRYPTION)
+ return new AEAD_Filter(new GCM_Encryption(block_cipher->clone(), tag_size));
+ else
+ return new AEAD_Filter(new GCM_Decryption(block_cipher->clone(), tag_size));
+ }
+#endif
+
+#endif
+ }
+
+ return nullptr;
+ }
+
+/*
+* Get a cipher object
+*/
+Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
+ Cipher_Dir direction,
+ Algorithm_Factory& af)
+ {
+ 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];
+
+ // check if it is a stream cipher first (easy case)
+ const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
+ if(stream_cipher)
+ return new StreamCipher_Filter(stream_cipher->clone());
+
+ const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
+ if(!block_cipher)
+ return nullptr;
+
+ if(algo_parts.size() >= 4)
+ return nullptr; // 4 part mode, not something we know about
+
+ if(algo_parts.size() < 2)
+ throw Lookup_Error("Cipher specification '" + algo_spec +
+ "' is missing mode identifier");
+
+ std::string mode = algo_parts[1];
+
+ std::string padding;
+ if(algo_parts.size() == 3)
+ padding = algo_parts[2];
+ else
+ padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
+
+ if(mode == "ECB" && padding == "CTS")
+ return nullptr;
+ else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
+ throw Invalid_Algorithm_Name(algo_spec);
+
+ Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding);
+ if(filt)
+ return filt;
+
+ if(padding != "NoPadding")
+ throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding);
+ else
+ throw Algorithm_Not_Found(cipher_name + "/" + mode);
+ }
+
+}
diff --git a/lib/engine/core_engine/def_pk_ops.cpp b/lib/engine/core_engine/def_pk_ops.cpp
new file mode 100644
index 000000000..e99945633
--- /dev/null
+++ b/lib/engine/core_engine/def_pk_ops.cpp
@@ -0,0 +1,170 @@
+/*
+* PK Operations
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ #include <botan/gost_3410.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ #include <botan/ecdh.h>
+#endif
+
+namespace Botan {
+
+PK_Ops::Encryption*
+Core_Engine::get_encryption_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new RSA_Public_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(const ElGamal_PublicKey* s = dynamic_cast<const ElGamal_PublicKey*>(&key))
+ return new ElGamal_Encryption_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Decryption*
+Core_Engine::get_decryption_op(const Private_Key& key, RandomNumberGenerator& rng) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new RSA_Private_Operation(*s, rng);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(const ElGamal_PrivateKey* s = dynamic_cast<const ElGamal_PrivateKey*>(&key))
+ return new ElGamal_Decryption_Operation(*s, rng);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Key_Agreement*
+Core_Engine::get_key_agreement_op(const Private_Key& key, RandomNumberGenerator& rng) const
+ {
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key))
+ return new DH_KA_Operation(*dh, rng);
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(const ECDH_PrivateKey* ecdh = dynamic_cast<const ECDH_PrivateKey*>(&key))
+ return new ECDH_KA_Operation(*ecdh);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Signature*
+Core_Engine::get_signature_op(const Private_Key& key, RandomNumberGenerator& rng) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new RSA_Private_Operation(*s, rng);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(const RW_PrivateKey* s = dynamic_cast<const RW_PrivateKey*>(&key))
+ return new RW_Signature_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key))
+ return new DSA_Signature_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(const ECDSA_PrivateKey* s = dynamic_cast<const ECDSA_PrivateKey*>(&key))
+ return new ECDSA_Signature_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(const GOST_3410_PrivateKey* s =
+ dynamic_cast<const GOST_3410_PrivateKey*>(&key))
+ return new GOST_3410_Signature_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(const NR_PrivateKey* s = dynamic_cast<const NR_PrivateKey*>(&key))
+ return new NR_Signature_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Verification*
+Core_Engine::get_verify_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new RSA_Public_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(const RW_PublicKey* s = dynamic_cast<const RW_PublicKey*>(&key))
+ return new RW_Verification_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key))
+ return new DSA_Verification_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(const ECDSA_PublicKey* s = dynamic_cast<const ECDSA_PublicKey*>(&key))
+ return new ECDSA_Verification_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(const GOST_3410_PublicKey* s =
+ dynamic_cast<const GOST_3410_PublicKey*>(&key))
+ return new GOST_3410_Verification_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(const NR_PublicKey* s = dynamic_cast<const NR_PublicKey*>(&key))
+ return new NR_Verification_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/core_engine/def_powm.cpp b/lib/engine/core_engine/def_powm.cpp
new file mode 100644
index 000000000..56a4b6844
--- /dev/null
+++ b/lib/engine/core_engine/def_powm.cpp
@@ -0,0 +1,24 @@
+/*
+* Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/internal/def_powm.h>
+
+namespace Botan {
+
+/*
+* Choose a modular exponentation algorithm
+*/
+Modular_Exponentiator*
+Core_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/lib/engine/core_engine/info.txt b/lib/engine/core_engine/info.txt
new file mode 100644
index 000000000..44843e26a
--- /dev/null
+++ b/lib/engine/core_engine/info.txt
@@ -0,0 +1,24 @@
+define CORE_ENGINE 20131128
+
+<header:internal>
+core_engine.h
+</header:internal>
+
+<source>
+core_modes.cpp
+def_pk_ops.cpp
+def_powm.cpp
+lookup_block.cpp
+lookup_hash.cpp
+lookup_mac.cpp
+lookup_stream.cpp
+lookup_pbkdf.cpp
+</source>
+
+<requires>
+algo_factory
+filters
+libstate
+mode_pad
+numbertheory
+</requires>
diff --git a/lib/engine/core_engine/lookup_block.cpp b/lib/engine/core_engine/lookup_block.cpp
new file mode 100644
index 000000000..0a9c02311
--- /dev/null
+++ b/lib/engine/core_engine/lookup_block.cpp
@@ -0,0 +1,298 @@
+/*
+* Block Cipher Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.h>
+
+#if defined(BOTAN_HAS_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ #include <botan/blowfish.h>
+#endif
+
+#if defined(BOTAN_HAS_CAMELLIA)
+ #include <botan/camellia.h>
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ #include <botan/cast128.h>
+ #include <botan/cast256.h>
+#endif
+
+#if defined(BOTAN_HAS_CASCADE)
+ #include <botan/cascade.h>
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ #include <botan/des.h>
+ #include <botan/desx.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_28147_89)
+ #include <botan/gost_28147.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_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_THREEFISH_512)
+ #include <botan/threefish.h>
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ #include <botan/xtea.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+BlockCipher* Core_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+
+#if defined(BOTAN_HAS_AES)
+ if(request.algo_name() == "AES-128")
+ return new AES_128;
+ if(request.algo_name() == "AES-192")
+ return new AES_192;
+ if(request.algo_name() == "AES-256")
+ return new AES_256;
+#endif
+
+#if defined(BOTAN_HAS_BLOWFISH)
+ if(request.algo_name() == "Blowfish")
+ return new Blowfish;
+#endif
+
+#if defined(BOTAN_HAS_CAMELLIA)
+ if(request.algo_name() == "Camellia-128")
+ return new Camellia_128;
+ if(request.algo_name() == "Camellia-192")
+ return new Camellia_192;
+ if(request.algo_name() == "Camellia-256")
+ return new Camellia_256;
+#endif
+
+#if defined(BOTAN_HAS_CAST)
+ if(request.algo_name() == "CAST-128")
+ return new CAST_128;
+ if(request.algo_name() == "CAST-256")
+ return new CAST_256;
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ if(request.algo_name() == "DES")
+ return new DES;
+ if(request.algo_name() == "DESX")
+ return new DESX;
+ if(request.algo_name() == "TripleDES")
+ return new TripleDES;
+#endif
+
+#if defined(BOTAN_HAS_GOST_28147_89)
+ if(request.algo_name() == "GOST-28147-89")
+ return new GOST_28147_89(request.arg(0, "R3411_94_TestParam"));
+#endif
+
+#if defined(BOTAN_HAS_IDEA)
+ if(request.algo_name() == "IDEA")
+ return new IDEA;
+#endif
+
+#if defined(BOTAN_HAS_KASUMI)
+ if(request.algo_name() == "KASUMI")
+ return new KASUMI;
+#endif
+
+#if defined(BOTAN_HAS_MARS)
+ if(request.algo_name() == "MARS")
+ return new MARS;
+#endif
+
+#if defined(BOTAN_HAS_MISTY1)
+ if(request.algo_name() == "MISTY1")
+ return new MISTY1(request.arg_as_integer(0, 8));
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON)
+ if(request.algo_name() == "Noekeon")
+ return new Noekeon;
+#endif
+
+#if defined(BOTAN_HAS_RC2)
+ if(request.algo_name() == "RC2")
+ return new RC2;
+#endif
+
+#if defined(BOTAN_HAS_RC5)
+ if(request.algo_name() == "RC5")
+ return new RC5(request.arg_as_integer(0, 12));
+#endif
+
+#if defined(BOTAN_HAS_RC6)
+ if(request.algo_name() == "RC6")
+ return new RC6;
+#endif
+
+#if defined(BOTAN_HAS_SAFER)
+ if(request.algo_name() == "SAFER-SK")
+ return new SAFER_SK(request.arg_as_integer(0, 10));
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ if(request.algo_name() == "SEED")
+ return new SEED;
+#endif
+
+#if defined(BOTAN_HAS_SERPENT)
+ if(request.algo_name() == "Serpent")
+ return new Serpent;
+#endif
+
+#if defined(BOTAN_HAS_SKIPJACK)
+ if(request.algo_name() == "Skipjack")
+ return new Skipjack;
+#endif
+
+#if defined(BOTAN_HAS_SQUARE)
+ if(request.algo_name() == "Square")
+ return new Square;
+#endif
+
+#if defined(BOTAN_HAS_TEA)
+ if(request.algo_name() == "TEA")
+ return new TEA;
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ if(request.algo_name() == "Twofish")
+ return new Twofish;
+#endif
+
+#if defined(BOTAN_HAS_TWOFISH)
+ if(request.algo_name() == "Threefish-512")
+ return new Threefish_512;
+#endif
+
+#if defined(BOTAN_HAS_XTEA)
+ if(request.algo_name() == "XTEA")
+ return new XTEA;
+#endif
+
+#if defined(BOTAN_HAS_LUBY_RACKOFF)
+ if(request.algo_name() == "Luby-Rackoff" && request.arg_count() == 1)
+ {
+ const HashFunction* hash = af.prototype_hash_function(request.arg(0));
+
+ if(hash)
+ return new LubyRackoff(hash->clone());
+ }
+#endif
+
+#if defined(BOTAN_HAS_CASCADE)
+ if(request.algo_name() == "Cascade" && request.arg_count() == 2)
+ {
+ const BlockCipher* c1 = af.prototype_block_cipher(request.arg(0));
+ const BlockCipher* c2 = af.prototype_block_cipher(request.arg(1));
+
+ if(c1 && c2)
+ return new Cascade_Cipher(c1->clone(), c2->clone());
+ }
+#endif
+
+#if defined(BOTAN_HAS_LION)
+ if(request.algo_name() == "Lion" && request.arg_count_between(2, 3))
+ {
+ const size_t block_size = request.arg_as_integer(2, 1024);
+
+ const HashFunction* hash =
+ af.prototype_hash_function(request.arg(0));
+
+ const StreamCipher* stream_cipher =
+ af.prototype_stream_cipher(request.arg(1));
+
+ if(!hash || !stream_cipher)
+ return nullptr;
+
+ return new Lion(hash->clone(), stream_cipher->clone(), block_size);
+ }
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/core_engine/lookup_hash.cpp b/lib/engine/core_engine/lookup_hash.cpp
new file mode 100644
index 000000000..7a9a0148d
--- /dev/null
+++ b/lib/engine/core_engine/lookup_hash.cpp
@@ -0,0 +1,238 @@
+/*
+* Hash Algorithms Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.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_BMW_512)
+ #include <botan/bmw_512.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_11)
+ #include <botan/gost_3411.h>
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ #include <botan/has160.h>
+#endif
+
+#if defined(BOTAN_HAS_KECCAK)
+ #include <botan/keccak.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_MD5)
+ #include <botan/md5.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_SHA2_32)
+ #include <botan/sha2_32.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA2_64)
+ #include <botan/sha2_64.h>
+#endif
+
+#if defined(BOTAN_HAS_SKEIN_512)
+ #include <botan/skein_512.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
+
+#if defined(BOTAN_HAS_COMB4P)
+ #include <botan/comb4p.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+HashFunction* Core_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+#if defined(BOTAN_HAS_ADLER32)
+ if(request.algo_name() == "Adler32")
+ return new Adler32;
+#endif
+
+#if defined(BOTAN_HAS_CRC24)
+ if(request.algo_name() == "CRC24")
+ return new CRC24;
+#endif
+
+#if defined(BOTAN_HAS_CRC32)
+ if(request.algo_name() == "CRC32")
+ return new CRC32;
+#endif
+
+#if defined(BOTAN_HAS_BMW_512)
+ if(request.algo_name() == "BMW-512")
+ return new BMW_512;
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_11)
+ if(request.algo_name() == "GOST-R-34.11-94")
+ return new GOST_34_11;
+#endif
+
+#if defined(BOTAN_HAS_HAS_160)
+ if(request.algo_name() == "HAS-160")
+ return new HAS_160;
+#endif
+
+#if defined(BOTAN_HAS_KECCAK)
+ if(request.algo_name() == "Keccak-1600")
+ return new Keccak_1600(request.arg_as_integer(0, 512));
+#endif
+
+#if defined(BOTAN_HAS_MD2)
+ if(request.algo_name() == "MD2")
+ return new MD2;
+#endif
+
+#if defined(BOTAN_HAS_MD4)
+ if(request.algo_name() == "MD4")
+ return new MD4;
+#endif
+
+#if defined(BOTAN_HAS_MD5)
+ if(request.algo_name() == "MD5")
+ return new MD5;
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_128)
+ if(request.algo_name() == "RIPEMD-128")
+ return new RIPEMD_128;
+#endif
+
+#if defined(BOTAN_HAS_RIPEMD_160)
+ if(request.algo_name() == "RIPEMD-160")
+ return new RIPEMD_160;
+#endif
+
+#if defined(BOTAN_HAS_SHA1)
+ if(request.algo_name() == "SHA-160")
+ return new SHA_160;
+#endif
+
+#if defined(BOTAN_HAS_SHA2_32)
+ if(request.algo_name() == "SHA-224")
+ return new SHA_224;
+ if(request.algo_name() == "SHA-256")
+ return new SHA_256;
+#endif
+
+#if defined(BOTAN_HAS_SHA2_64)
+ if(request.algo_name() == "SHA-384")
+ return new SHA_384;
+ if(request.algo_name() == "SHA-512")
+ return new SHA_512;
+#endif
+
+#if defined(BOTAN_HAS_TIGER)
+ if(request.algo_name() == "Tiger")
+ return new Tiger(request.arg_as_integer(0, 24), // hash output
+ request.arg_as_integer(1, 3)); // # passes
+#endif
+
+#if defined(BOTAN_HAS_SKEIN_512)
+ if(request.algo_name() == "Skein-512")
+ return new Skein_512(request.arg_as_integer(0, 512),
+ request.arg(1, ""));
+#endif
+
+#if defined(BOTAN_HAS_WHIRLPOOL)
+ if(request.algo_name() == "Whirlpool")
+ return new Whirlpool;
+#endif
+
+#if defined(BOTAN_HAS_COMB4P)
+ if(request.algo_name() == "Comb4P" && request.arg_count() == 2)
+ {
+ const HashFunction* h1 = af.prototype_hash_function(request.arg(0));
+ const HashFunction* h2 = af.prototype_hash_function(request.arg(1));
+
+ if(h1 && h2)
+ return new Comb4P(h1->clone(), h2->clone());
+ }
+#endif
+
+#if defined(BOTAN_HAS_PARALLEL_HASH)
+
+ if(request.algo_name() == "Parallel")
+ {
+ std::vector<const HashFunction*> hash_prototypes;
+
+ /* First pass, just get the prototypes (no memory allocation). Then
+ if all were found, replace each prototype with a newly created clone
+ */
+ for(size_t i = 0; i != request.arg_count(); ++i)
+ {
+ const HashFunction* hash = af.prototype_hash_function(request.arg(i));
+ if(!hash)
+ return nullptr;
+
+ hash_prototypes.push_back(hash);
+ }
+
+ std::vector<HashFunction*> hashes;
+ for(size_t i = 0; i != hash_prototypes.size(); ++i)
+ hashes.push_back(hash_prototypes[i]->clone());
+
+ return new Parallel(hashes);
+ }
+
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/core_engine/lookup_mac.cpp b/lib/engine/core_engine/lookup_mac.cpp
new file mode 100644
index 000000000..32275b559
--- /dev/null
+++ b/lib/engine/core_engine/lookup_mac.cpp
@@ -0,0 +1,70 @@
+/*
+* MAC Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.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*
+Core_Engine::find_mac(const SCAN_Name& request,
+ Algorithm_Factory& af) const
+ {
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ if(request.algo_name() == "CBC-MAC" && request.arg_count() == 1)
+ return new CBC_MAC(af.make_block_cipher(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ if(request.algo_name() == "CMAC" && request.arg_count() == 1)
+ return new CMAC(af.make_block_cipher(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ if(request.algo_name() == "HMAC" && request.arg_count() == 1)
+ return new HMAC(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_SSL3_MAC)
+ if(request.algo_name() == "SSL3-MAC" && request.arg_count() == 1)
+ return new SSL3_MAC(af.make_hash_function(request.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ if(request.algo_name() == "X9.19-MAC" && request.arg_count() == 0)
+ return new ANSI_X919_MAC(af.make_block_cipher("DES"));
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/core_engine/lookup_pbkdf.cpp b/lib/engine/core_engine/lookup_pbkdf.cpp
new file mode 100644
index 000000000..bfd2c8bc2
--- /dev/null
+++ b/lib/engine/core_engine/lookup_pbkdf.cpp
@@ -0,0 +1,43 @@
+/*
+* PBKDF Lookup
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/scan_name.h>
+#include <botan/algo_factory.h>
+
+#if defined(BOTAN_HAS_PBKDF1)
+ #include <botan/pbkdf1.h>
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ #include <botan/pbkdf2.h>
+#endif
+
+namespace Botan {
+
+PBKDF* Core_Engine::find_pbkdf(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const
+ {
+#if defined(BOTAN_HAS_PBKDF1)
+ if(algo_spec.algo_name() == "PBKDF1" && algo_spec.arg_count() == 1)
+ return new PKCS5_PBKDF1(af.make_hash_function(algo_spec.arg(0)));
+#endif
+
+#if defined(BOTAN_HAS_PBKDF2)
+ if(algo_spec.algo_name() == "PBKDF2" && algo_spec.arg_count() == 1)
+ {
+ if(const MessageAuthenticationCode* mac_proto = af.prototype_mac(algo_spec.arg(0)))
+ return new PKCS5_PBKDF2(mac_proto->clone());
+
+ return new PKCS5_PBKDF2(af.make_mac("HMAC(" + algo_spec.arg(0) + ")"));
+ }
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/core_engine/lookup_stream.cpp b/lib/engine/core_engine/lookup_stream.cpp
new file mode 100644
index 000000000..b26bbedcd
--- /dev/null
+++ b/lib/engine/core_engine/lookup_stream.cpp
@@ -0,0 +1,43 @@
+/*
+* Stream Cipher Lookup
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/core_engine.h>
+#include <botan/scan_name.h>
+
+#if defined(BOTAN_HAS_RC4)
+ #include <botan/rc4.h>
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ #include <botan/salsa20.h>
+#endif
+
+namespace Botan {
+
+/*
+* Look for an algorithm with this name
+*/
+StreamCipher*
+Core_Engine::find_stream_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_RC4)
+ if(request.algo_name() == "RC4")
+ return new RC4(request.arg_as_integer(0, 0));
+ if(request.algo_name() == "RC4_drop")
+ return new RC4(768);
+#endif
+
+#if defined(BOTAN_HAS_SALSA20)
+ if(request.algo_name() == "Salsa20")
+ return new Salsa20;
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/dyn_engine/dyn_engine.cpp b/lib/engine/dyn_engine/dyn_engine.cpp
new file mode 100644
index 000000000..078ec4b83
--- /dev/null
+++ b/lib/engine/dyn_engine/dyn_engine.cpp
@@ -0,0 +1,63 @@
+/**
+* Dynamically Loaded Engine
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/dyn_engine.h>
+#include <botan/internal/dyn_load.h>
+
+namespace Botan {
+
+namespace {
+
+extern "C" {
+ typedef Engine* (*creator_func)(void);
+ typedef u32bit (*module_version_func)(void);
+}
+
+}
+
+Dynamically_Loaded_Engine::Dynamically_Loaded_Engine(
+ const std::string& library_path) :
+ engine(nullptr)
+ {
+ lib = new Dynamically_Loaded_Library(library_path);
+
+ try
+ {
+ module_version_func get_version =
+ lib->resolve<module_version_func>("module_version");
+
+ const u32bit mod_version = get_version();
+
+ if(mod_version != 20101003)
+ throw std::runtime_error("Incompatible version in " +
+ library_path + " of " +
+ std::to_string(mod_version));
+
+ creator_func creator =
+ lib->resolve<creator_func>("create_engine");
+
+ engine = creator();
+
+ if(!engine)
+ throw std::runtime_error("Creator function in " +
+ library_path + " failed");
+ }
+ catch(...)
+ {
+ delete lib;
+ lib = nullptr;
+ throw;
+ }
+ }
+
+Dynamically_Loaded_Engine::~Dynamically_Loaded_Engine()
+ {
+ delete engine;
+ delete lib;
+ }
+
+}
diff --git a/lib/engine/dyn_engine/dyn_engine.h b/lib/engine/dyn_engine/dyn_engine.h
new file mode 100644
index 000000000..39e13ab36
--- /dev/null
+++ b/lib/engine/dyn_engine/dyn_engine.h
@@ -0,0 +1,115 @@
+/**
+* Dynamically Loaded Engine
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_DYN_LOADED_ENGINE_H__
+#define BOTAN_DYN_LOADED_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Dynamically_Loaded_Engine just proxies the requests to the underlying
+* Engine object, and handles load/unload details
+*/
+class BOTAN_DLL Dynamically_Loaded_Engine : public Engine
+ {
+ public:
+ /**
+ * @param lib_path full pathname to DLL to load
+ */
+ Dynamically_Loaded_Engine(const std::string& lib_path);
+
+ Dynamically_Loaded_Engine(const Dynamically_Loaded_Engine&) = delete;
+
+ Dynamically_Loaded_Engine& operator=(const Dynamically_Loaded_Engine&) = delete;
+
+ ~Dynamically_Loaded_Engine();
+
+ std::string provider_name() const override { return engine->provider_name(); }
+
+ BlockCipher* find_block_cipher(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override
+ {
+ return engine->find_block_cipher(algo_spec, af);
+ }
+
+ StreamCipher* find_stream_cipher(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override
+ {
+ return engine->find_stream_cipher(algo_spec, af);
+ }
+
+ HashFunction* find_hash(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override
+ {
+ return engine->find_hash(algo_spec, af);
+ }
+
+ MessageAuthenticationCode* find_mac(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override
+ {
+ return engine->find_mac(algo_spec, af);
+ }
+
+ PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const override
+ {
+ return engine->find_pbkdf(algo_spec, af);
+ }
+
+ Modular_Exponentiator* mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints hints) const override
+ {
+ return engine->mod_exp(n, hints);
+ }
+
+ Keyed_Filter* get_cipher(const std::string& algo_spec,
+ Cipher_Dir dir,
+ Algorithm_Factory& af)
+ {
+ return engine->get_cipher(algo_spec, dir, af);
+ }
+
+ PK_Ops::Key_Agreement*
+ get_key_agreement_op(const Private_Key& key, RandomNumberGenerator& rng) const override
+ {
+ return engine->get_key_agreement_op(key, rng);
+ }
+
+ PK_Ops::Signature*
+ get_signature_op(const Private_Key& key, RandomNumberGenerator& rng) const override
+ {
+ return engine->get_signature_op(key, rng);
+ }
+
+ PK_Ops::Verification*
+ get_verify_op(const Public_Key& key, RandomNumberGenerator& rng) const override
+ {
+ return engine->get_verify_op(key, rng);
+ }
+
+ PK_Ops::Encryption*
+ get_encryption_op(const Public_Key& key, RandomNumberGenerator& rng) const override
+ {
+ return engine->get_encryption_op(key, rng);
+ }
+
+ PK_Ops::Decryption*
+ get_decryption_op(const Private_Key& key, RandomNumberGenerator& rng) const override
+ {
+ return engine->get_decryption_op(key, rng);
+ }
+
+ private:
+ class Dynamically_Loaded_Library* lib;
+ Engine* engine;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/dyn_engine/info.txt b/lib/engine/dyn_engine/info.txt
new file mode 100644
index 000000000..54379f501
--- /dev/null
+++ b/lib/engine/dyn_engine/info.txt
@@ -0,0 +1,14 @@
+define DYNAMICALLY_LOADED_ENGINE 20131128
+
+<header:public>
+dyn_engine.h
+</header:public>
+
+<source>
+dyn_engine.cpp
+</source>
+
+<requires>
+engine
+dyn_load
+</requires>
diff --git a/lib/engine/engine.cpp b/lib/engine/engine.cpp
new file mode 100644
index 000000000..a50f1e7b2
--- /dev/null
+++ b/lib/engine/engine.cpp
@@ -0,0 +1,91 @@
+/*
+* Engine
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+BlockCipher*
+Engine::find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const
+ {
+ return nullptr;
+ }
+
+StreamCipher*
+Engine::find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const
+ {
+ return nullptr;
+ }
+
+HashFunction*
+Engine::find_hash(const SCAN_Name&,
+ Algorithm_Factory&) const
+ {
+ return nullptr;
+ }
+
+MessageAuthenticationCode*
+Engine::find_mac(const SCAN_Name&,
+ Algorithm_Factory&) const
+ {
+ return nullptr;
+ }
+
+PBKDF*
+Engine::find_pbkdf(const SCAN_Name&,
+ Algorithm_Factory&) const
+ {
+ return nullptr;
+ }
+
+Modular_Exponentiator*
+Engine::mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const
+ {
+ return nullptr;
+ }
+
+Keyed_Filter* Engine::get_cipher(const std::string&,
+ Cipher_Dir,
+ Algorithm_Factory&)
+ {
+ return nullptr;
+ }
+
+PK_Ops::Key_Agreement*
+Engine::get_key_agreement_op(const Private_Key&, RandomNumberGenerator&) const
+ {
+ return nullptr;
+ }
+
+PK_Ops::Signature*
+Engine::get_signature_op(const Private_Key&, RandomNumberGenerator&) const
+ {
+ return nullptr;
+ }
+
+PK_Ops::Verification*
+Engine::get_verify_op(const Public_Key&, RandomNumberGenerator&) const
+ {
+ return nullptr;
+ }
+
+PK_Ops::Encryption*
+Engine::get_encryption_op(const Public_Key&, RandomNumberGenerator&) const
+ {
+ return nullptr;
+ }
+
+PK_Ops::Decryption*
+Engine::get_decryption_op(const Private_Key&, RandomNumberGenerator&) const
+ {
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/engine.h b/lib/engine/engine.h
new file mode 100644
index 000000000..a03a6e1ec
--- /dev/null
+++ b/lib/engine/engine.h
@@ -0,0 +1,150 @@
+/*
+* Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_H__
+#define BOTAN_ENGINE_H__
+
+#include <botan/scan_name.h>
+#include <botan/block_cipher.h>
+#include <botan/stream_cipher.h>
+#include <botan/hash.h>
+#include <botan/mac.h>
+#include <botan/pbkdf.h>
+#include <botan/pow_mod.h>
+#include <botan/pk_keys.h>
+#include <botan/pk_ops.h>
+
+namespace Botan {
+
+class Algorithm_Factory;
+class Keyed_Filter;
+class RandomNumberGenerator;
+
+/**
+* Base class for all engines. All non-pure virtual functions simply
+* return NULL, indicating the algorithm in question is not
+* supported. Subclasses can reimplement whichever function(s)
+* they want to hook in a particular type.
+*/
+class BOTAN_DLL Engine
+ {
+ public:
+ virtual ~Engine() {}
+
+ /**
+ * @return name of this engine
+ */
+ virtual std::string provider_name() const = 0;
+
+ /**
+ * @param algo_spec the algorithm name/specification
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual BlockCipher*
+ find_block_cipher(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const;
+
+ /**
+ * @param algo_spec the algorithm name/specification
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual StreamCipher*
+ find_stream_cipher(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const;
+
+ /**
+ * @param algo_spec the algorithm name/specification
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual HashFunction*
+ find_hash(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const;
+
+ /**
+ * @param algo_spec the algorithm name/specification
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual MessageAuthenticationCode*
+ find_mac(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const;
+
+ /**
+ * @param algo_spec the algorithm name/specification
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual PBKDF* find_pbkdf(const SCAN_Name& algo_spec,
+ Algorithm_Factory& af) const;
+
+ /**
+ * @param n the modulus
+ * @param hints any use hints
+ * @return newly allocated object, or NULL
+ */
+ virtual Modular_Exponentiator*
+ mod_exp(const BigInt& n,
+ Power_Mod::Usage_Hints hints) const;
+
+ /**
+ * Return a new cipher object
+ * @param algo_spec the algorithm name/specification
+ * @param dir specifies if encryption or decryption is desired
+ * @param af an algorithm factory object
+ * @return newly allocated object, or NULL
+ */
+ virtual Keyed_Filter* get_cipher(const std::string& algo_spec,
+ Cipher_Dir dir,
+ Algorithm_Factory& af);
+
+ /**
+ * Return a new operator object for this key, if possible
+ * @param key the key we want an operator for
+ * @return newly allocated operator object, or NULL
+ */
+ virtual PK_Ops::Key_Agreement*
+ get_key_agreement_op(const Private_Key& key, RandomNumberGenerator& rng) const;
+
+ /**
+ * Return a new operator object for this key, if possible
+ * @param key the key we want an operator for
+ * @return newly allocated operator object, or NULL
+ */
+ virtual PK_Ops::Signature*
+ get_signature_op(const Private_Key& key, RandomNumberGenerator& rng) const;
+
+ /**
+ * Return a new operator object for this key, if possible
+ * @param key the key we want an operator for
+ * @return newly allocated operator object, or NULL
+ */
+ virtual PK_Ops::Verification*
+ get_verify_op(const Public_Key& key, RandomNumberGenerator& rng) const;
+
+ /**
+ * Return a new operator object for this key, if possible
+ * @param key the key we want an operator for
+ * @return newly allocated operator object, or NULL
+ */
+ virtual PK_Ops::Encryption*
+ get_encryption_op(const Public_Key& key, RandomNumberGenerator& rng) const;
+
+ /**
+ * Return a new operator object for this key, if possible
+ * @param key the key we want an operator for
+ * @return newly allocated operator object, or NULL
+ */
+ virtual PK_Ops::Decryption*
+ get_decryption_op(const Private_Key& key, RandomNumberGenerator& rng) const;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/gnump/gmp_mem.cpp b/lib/engine/gnump/gmp_mem.cpp
new file mode 100644
index 000000000..b5a5a303e
--- /dev/null
+++ b/lib/engine/gnump/gmp_mem.cpp
@@ -0,0 +1,83 @@
+/*
+* GNU MP Memory Handlers
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/gnump_engine.h>
+#include <cstring>
+#include <atomic>
+#include <gmp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* For keeping track of existing GMP_Engines and only
+* resetting the memory when none are in use.
+*/
+std::atomic<size_t> gmp_alloc_refcnt(0);
+
+/*
+* Allocation Function for GNU MP
+*/
+void* gmp_malloc(size_t n)
+ {
+ // Maintain alignment, mlock goes for sizeof(T) alignment
+ if(n % 8 == 0)
+ return secure_allocator<u64bit>().allocate(n / 8);
+ else if(n % 4 == 0)
+ return secure_allocator<u32bit>().allocate(n / 4);
+ else if(n % 2 == 0)
+ return secure_allocator<u16bit>().allocate(n / 2);
+
+ return secure_allocator<byte>().allocate(n);
+ }
+
+/*
+* Deallocation Function for GNU MP
+*/
+void gmp_free(void* ptr, size_t n)
+ {
+ secure_allocator<byte>().deallocate(static_cast<byte*>(ptr), n);
+ }
+
+/*
+* Reallocation Function for GNU MP
+*/
+void* gmp_realloc(void* ptr, size_t old_n, size_t new_n)
+ {
+ void* new_buf = gmp_malloc(new_n);
+ std::memcpy(new_buf, ptr, std::min(old_n, new_n));
+ gmp_free(ptr, old_n);
+ return new_buf;
+ }
+
+}
+
+/*
+* GMP_Engine Constructor
+*/
+GMP_Engine::GMP_Engine()
+ {
+ /*
+ if(gmp_alloc_refcnt == 0)
+ mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free);
+
+ gmp_alloc_refcnt++;
+ */
+ }
+
+GMP_Engine::~GMP_Engine()
+ {
+ /*
+ --gmp_alloc_refcnt;
+
+ if(gmp_alloc_refcnt == 0)
+ mp_set_memory_functions(NULL, NULL, NULL);
+ */
+ }
+
+}
diff --git a/lib/engine/gnump/gmp_powm.cpp b/lib/engine/gnump/gmp_powm.cpp
new file mode 100644
index 000000000..70c2b2f5e
--- /dev/null
+++ b/lib/engine/gnump/gmp_powm.cpp
@@ -0,0 +1,53 @@
+/*
+* GMP Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/gnump_engine.h>
+#include <botan/internal/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/lib/engine/gnump/gmp_wrap.cpp b/lib/engine/gnump/gmp_wrap.cpp
new file mode 100644
index 000000000..974593d02
--- /dev/null
+++ b/lib/engine/gnump/gmp_wrap.cpp
@@ -0,0 +1,101 @@
+/*
+* GMP Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/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[], size_t 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[], size_t length) const
+ {
+ size_t dummy = 0;
+ mpz_export(out + (length - bytes()), &dummy, 1, 1, 0, 0, value);
+ }
+
+/*
+* Return the number of significant bytes
+*/
+size_t 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;
+
+ word* reg = out.mutable_data();
+
+ mpz_export(reg, &dummy, -1, sizeof(word), 0, 0, value);
+
+ if(mpz_sgn(value) < 0)
+ out.flip_sign();
+
+ return out;
+ }
+
+}
diff --git a/lib/engine/gnump/gmp_wrap.h b/lib/engine/gnump/gmp_wrap.h
new file mode 100644
index 000000000..291d65a01
--- /dev/null
+++ b/lib/engine/gnump/gmp_wrap.h
@@ -0,0 +1,41 @@
+/*
+* GMP MPZ Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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. For internal use only.
+*/
+class GMP_MPZ
+ {
+ public:
+ mpz_t value;
+
+ BigInt to_bigint() const;
+ void encode(byte[], size_t) const;
+ size_t bytes() const;
+
+ secure_vector<byte> to_bytes() const
+ { return BigInt::encode_locked(to_bigint()); }
+
+ GMP_MPZ& operator=(const GMP_MPZ&);
+
+ GMP_MPZ(const GMP_MPZ&);
+ GMP_MPZ(const BigInt& = 0);
+ GMP_MPZ(const byte[], size_t);
+ ~GMP_MPZ();
+ };
+
+}
+
+#endif
diff --git a/lib/engine/gnump/gnump_engine.h b/lib/engine/gnump/gnump_engine.h
new file mode 100644
index 000000000..ccc723514
--- /dev/null
+++ b/lib/engine/gnump/gnump_engine.h
@@ -0,0 +1,44 @@
+/*
+* GMP Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_GMP_H__
+#define BOTAN_ENGINE_GMP_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Engine using GNU MP
+*/
+class GMP_Engine : public Engine
+ {
+ public:
+ GMP_Engine();
+ ~GMP_Engine();
+
+ std::string provider_name() const override { return "gmp"; }
+
+ PK_Ops::Key_Agreement*
+ get_key_agreement_op(const Private_Key& key, RandomNumberGenerator&) const override;
+
+ PK_Ops::Signature*
+ get_signature_op(const Private_Key& key, RandomNumberGenerator&) const override;
+
+ PK_Ops::Verification* get_verify_op(const Public_Key& key, RandomNumberGenerator&) const override;
+
+ PK_Ops::Encryption* get_encryption_op(const Public_Key& key, RandomNumberGenerator&) const override;
+
+ PK_Ops::Decryption* get_decryption_op(const Private_Key& key, RandomNumberGenerator&) const override;
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const override;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/gnump/gnump_pk.cpp b/lib/engine/gnump/gnump_pk.cpp
new file mode 100644
index 000000000..29e172d47
--- /dev/null
+++ b/lib/engine/gnump/gnump_pk.cpp
@@ -0,0 +1,338 @@
+/*
+* GnuMP PK operations
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/gnump_engine.h>
+#include <botan/internal/gmp_wrap.h>
+#include <gmp.h>
+
+/* GnuMP 5.0 and later have a side-channel resistent powm */
+#if defined(HAVE_MPZ_POWM_SEC)
+ #undef mpz_powm
+ #define mpz_powm mpz_powm_sec
+#endif
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement
+ {
+ public:
+ GMP_DH_KA_Operation(const DH_PrivateKey& dh) :
+ x(dh.get_x()), p(dh.group_p()) {}
+
+ secure_vector<byte> agree(const byte w[], size_t w_len)
+ {
+ GMP_MPZ z(w, w_len);
+ mpz_powm(z.value, z.value, x.value, p.value);
+ return z.to_bytes();
+ }
+
+ private:
+ GMP_MPZ x, p;
+ };
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+
+class GMP_DSA_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ GMP_DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
+ x(dsa.get_x()),
+ p(dsa.group_p()),
+ q(dsa.group_q()),
+ g(dsa.group_g()),
+ q_bits(dsa.group_q().bits()) {}
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return (q_bits + 7) / 8; }
+ size_t max_input_bits() const { return q_bits; }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+ private:
+ const GMP_MPZ x, p, q, g;
+ size_t q_bits;
+ };
+
+secure_vector<byte>
+GMP_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ const size_t q_bytes = (q_bits + 7) / 8;
+
+ rng.add_entropy(msg, msg_len);
+
+ BigInt k_bn;
+ do
+ k_bn.randomize(rng, q_bits);
+ while(k_bn >= q.to_bigint());
+
+ GMP_MPZ i(msg, msg_len);
+ 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");
+
+ secure_vector<byte> output(2*q_bytes);
+ r.encode(&output[0], q_bytes);
+ s.encode(&output[q_bytes], q_bytes);
+ return output;
+ }
+
+class GMP_DSA_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ GMP_DSA_Verification_Operation(const DSA_PublicKey& dsa) :
+ y(dsa.get_y()),
+ p(dsa.group_p()),
+ q(dsa.group_q()),
+ g(dsa.group_g()),
+ q_bits(dsa.group_q().bits()) {}
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return (q_bits + 7) / 8; }
+ size_t max_input_bits() const { return q_bits; }
+
+ bool with_recovery() const { return false; }
+
+ bool verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len);
+ private:
+ const GMP_MPZ y, p, q, g;
+ size_t q_bits;
+ };
+
+bool GMP_DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len)
+ {
+ const size_t 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;
+ }
+
+#endif
+
+#if defined(BOTAN_HAS_RSA)
+
+class GMP_RSA_Private_Operation : public PK_Ops::Signature,
+ public PK_Ops::Decryption
+ {
+ public:
+ GMP_RSA_Private_Operation(const RSA_PrivateKey& rsa) :
+ mod(rsa.get_n()),
+ p(rsa.get_p()),
+ q(rsa.get_q()),
+ d1(rsa.get_d1()),
+ d2(rsa.get_d2()),
+ c(rsa.get_c()),
+ n_bits(rsa.get_n().bits())
+ {}
+
+ size_t max_input_bits() const { return (n_bits - 1); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
+ {
+ BigInt m(msg, msg_len);
+ BigInt x = private_op(m);
+ return BigInt::encode_1363(x, (n_bits + 7) / 8);
+ }
+
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(private_op(m));
+ }
+
+ private:
+ BigInt private_op(const BigInt& m) const;
+
+ GMP_MPZ mod, p, q, d1, d2, c;
+ size_t n_bits;
+ };
+
+BigInt GMP_RSA_Private_Operation::private_op(const BigInt& m) const
+ {
+ GMP_MPZ j1, j2, h(m);
+
+ 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();
+ }
+
+class GMP_RSA_Public_Operation : public PK_Ops::Verification,
+ public PK_Ops::Encryption
+ {
+ public:
+ GMP_RSA_Public_Operation(const RSA_PublicKey& rsa) :
+ n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n())
+ {}
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+ bool with_recovery() const { return true; }
+
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_1363(public_op(m), n.bytes());
+ }
+
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(public_op(m));
+ }
+
+ private:
+ BigInt public_op(const BigInt& m) const
+ {
+ if(m >= n)
+ throw Invalid_Argument("RSA public op - input is too large");
+
+ GMP_MPZ m_gmp(m);
+ mpz_powm(m_gmp.value, m_gmp.value, e.value, mod.value);
+ return m_gmp.to_bigint();
+ }
+
+ const BigInt& n;
+ const GMP_MPZ e, mod;
+ };
+
+#endif
+
+}
+
+PK_Ops::Key_Agreement*
+GMP_Engine::get_key_agreement_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key))
+ return new GMP_DH_KA_Operation(*dh);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Signature*
+GMP_Engine::get_signature_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new GMP_RSA_Private_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key))
+ return new GMP_DSA_Signature_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Verification*
+GMP_Engine::get_verify_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new GMP_RSA_Public_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key))
+ return new GMP_DSA_Verification_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Encryption*
+GMP_Engine::get_encryption_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new GMP_RSA_Public_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+PK_Ops::Decryption*
+GMP_Engine::get_decryption_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new GMP_RSA_Private_Operation(*s);
+#endif
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/gnump/info.txt b/lib/engine/gnump/info.txt
new file mode 100644
index 000000000..ad03339e4
--- /dev/null
+++ b/lib/engine/gnump/info.txt
@@ -0,0 +1,23 @@
+define ENGINE_GNU_MP 20131128
+
+load_on request
+
+<libs>
+all -> gmp
+</libs>
+
+<header:internal>
+gnump_engine.h
+gmp_wrap.h
+</header:internal>
+
+<source>
+gmp_mem.cpp
+gmp_powm.cpp
+gmp_wrap.cpp
+gnump_pk.cpp
+</source>
+
+<requires>
+bigint
+</requires>
diff --git a/lib/engine/info.txt b/lib/engine/info.txt
new file mode 100644
index 000000000..800a007a1
--- /dev/null
+++ b/lib/engine/info.txt
@@ -0,0 +1,20 @@
+define ENGINES 20131128
+
+<header:public>
+engine.h
+</header:public>
+
+<source>
+engine.cpp
+</source>
+
+<requires>
+block
+hash
+libstate
+mac
+numbertheory
+pbkdf
+pubkey
+stream
+</requires>
diff --git a/lib/engine/openssl/bn_powm.cpp b/lib/engine/openssl/bn_powm.cpp
new file mode 100644
index 000000000..ac06fbe77
--- /dev/null
+++ b/lib/engine/openssl/bn_powm.cpp
@@ -0,0 +1,54 @@
+/*
+* OpenSSL Modular Exponentiation
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/openssl_engine.h>
+#include <botan/internal/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.ptr(), base.ptr(), exp.ptr(), mod.ptr(), ctx.ptr());
+ 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/lib/engine/openssl/bn_wrap.cpp b/lib/engine/openssl/bn_wrap.cpp
new file mode 100644
index 000000000..0a7e42368
--- /dev/null
+++ b/lib/engine/openssl/bn_wrap.cpp
@@ -0,0 +1,116 @@
+/*
+* OpenSSL BN Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/bn_wrap.h>
+
+namespace Botan {
+
+/*
+* OSSL_BN Constructor
+*/
+OSSL_BN::OSSL_BN(const BigInt& in)
+ {
+ m_bn = BN_new();
+ secure_vector<byte> encoding = BigInt::encode_locked(in);
+ if(in != 0)
+ BN_bin2bn(&encoding[0], encoding.size(), m_bn);
+ }
+
+/*
+* OSSL_BN Constructor
+*/
+OSSL_BN::OSSL_BN(const byte in[], size_t length)
+ {
+ m_bn = BN_new();
+ BN_bin2bn(in, length, m_bn);
+ }
+
+/*
+* OSSL_BN Copy Constructor
+*/
+OSSL_BN::OSSL_BN(const OSSL_BN& other)
+ {
+ m_bn = BN_dup(other.m_bn);
+ }
+
+/*
+* OSSL_BN Destructor
+*/
+OSSL_BN::~OSSL_BN()
+ {
+ BN_clear_free(m_bn);
+ }
+
+/*
+* OSSL_BN Assignment Operator
+*/
+OSSL_BN& OSSL_BN::operator=(const OSSL_BN& other)
+ {
+ BN_copy(m_bn, other.m_bn);
+ return (*this);
+ }
+
+/*
+* Export the BIGNUM as a bytestring
+*/
+void OSSL_BN::encode(byte out[], size_t length) const
+ {
+ BN_bn2bin(m_bn, out + (length - bytes()));
+ }
+
+/*
+* Return the number of significant bytes
+*/
+size_t OSSL_BN::bytes() const
+ {
+ return BN_num_bytes(m_bn);
+ }
+
+/*
+* OpenSSL to BigInt Conversions
+*/
+BigInt OSSL_BN::to_bigint() const
+ {
+ secure_vector<byte> out(bytes());
+ BN_bn2bin(m_bn, &out[0]);
+ return BigInt::decode(out);
+ }
+
+/*
+* OSSL_BN_CTX Constructor
+*/
+OSSL_BN_CTX::OSSL_BN_CTX()
+ {
+ m_ctx = BN_CTX_new();
+ }
+
+/*
+* OSSL_BN_CTX Copy Constructor
+*/
+OSSL_BN_CTX::OSSL_BN_CTX(const OSSL_BN_CTX&)
+ {
+ m_ctx = BN_CTX_new();
+ }
+
+/*
+* OSSL_BN_CTX Destructor
+*/
+OSSL_BN_CTX::~OSSL_BN_CTX()
+ {
+ BN_CTX_free(m_ctx);
+ }
+
+/*
+* OSSL_BN_CTX Assignment Operator
+*/
+OSSL_BN_CTX& OSSL_BN_CTX::operator=(const OSSL_BN_CTX&)
+ {
+ m_ctx = BN_CTX_new();
+ return (*this);
+ }
+
+}
diff --git a/lib/engine/openssl/bn_wrap.h b/lib/engine/openssl/bn_wrap.h
new file mode 100644
index 000000000..12bcec152
--- /dev/null
+++ b/lib/engine/openssl/bn_wrap.h
@@ -0,0 +1,60 @@
+/*
+* OpenSSL BN Wrapper
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#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. For internal use only.
+*/
+class OSSL_BN
+ {
+ public:
+ BigInt to_bigint() const;
+ void encode(byte[], size_t) const;
+ size_t bytes() const;
+
+ secure_vector<byte> to_bytes() const
+ { return BigInt::encode_locked(to_bigint()); }
+
+ OSSL_BN& operator=(const OSSL_BN&);
+
+ OSSL_BN(const OSSL_BN&);
+ OSSL_BN(const BigInt& = 0);
+ OSSL_BN(const byte[], size_t);
+ ~OSSL_BN();
+
+ BIGNUM* ptr() const { return m_bn; }
+ private:
+ BIGNUM* m_bn;
+ };
+
+/**
+* Lightweight OpenSSL BN_CTX wrapper. For internal use only.
+*/
+class OSSL_BN_CTX
+ {
+ public:
+ OSSL_BN_CTX& operator=(const OSSL_BN_CTX&);
+
+ OSSL_BN_CTX();
+ OSSL_BN_CTX(const OSSL_BN_CTX&);
+ ~OSSL_BN_CTX();
+
+ BN_CTX* ptr() const { return m_ctx; }
+ private:
+ BN_CTX* m_ctx;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/openssl/info.txt b/lib/engine/openssl/info.txt
new file mode 100644
index 000000000..d500816d5
--- /dev/null
+++ b/lib/engine/openssl/info.txt
@@ -0,0 +1,25 @@
+define ENGINE_OPENSSL 20131128
+
+load_on request
+
+<libs>
+all -> crypto
+</libs>
+
+<header:internal>
+openssl_engine.h
+bn_wrap.h
+</header:internal>
+
+<source>
+bn_powm.cpp
+bn_wrap.cpp
+ossl_arc4.cpp
+ossl_bc.cpp
+ossl_md.cpp
+ossl_pk.cpp
+</source>
+
+<requires>
+bigint
+</requires>
diff --git a/lib/engine/openssl/openssl_engine.h b/lib/engine/openssl/openssl_engine.h
new file mode 100644
index 000000000..90f315c00
--- /dev/null
+++ b/lib/engine/openssl/openssl_engine.h
@@ -0,0 +1,49 @@
+/*
+* OpenSSL Engine
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ENGINE_OPENSSL_H__
+#define BOTAN_ENGINE_OPENSSL_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* OpenSSL Engine
+*/
+class OpenSSL_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const override { return "openssl"; }
+
+ PK_Ops::Key_Agreement*
+ get_key_agreement_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Signature*
+ get_signature_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Verification* get_verify_op(const Public_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Encryption* get_encryption_op(const Public_Key& key, RandomNumberGenerator& rng) const override;
+
+ PK_Ops::Decryption* get_decryption_op(const Private_Key& key, RandomNumberGenerator& rng) const override;
+
+ Modular_Exponentiator* mod_exp(const BigInt&,
+ Power_Mod::Usage_Hints) const override;
+
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const override;
+
+ StreamCipher* find_stream_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const override;
+
+ HashFunction* find_hash(const SCAN_Name&, Algorithm_Factory&) const override;
+ };
+
+}
+
+#endif
diff --git a/lib/engine/openssl/ossl_arc4.cpp b/lib/engine/openssl/ossl_arc4.cpp
new file mode 100644
index 000000000..0eb404af1
--- /dev/null
+++ b/lib/engine/openssl/ossl_arc4.cpp
@@ -0,0 +1,89 @@
+/*
+* OpenSSL RC4
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/openssl_engine.h>
+#include <botan/parsing.h>
+#include <openssl/rc4.h>
+
+namespace Botan {
+
+namespace {
+
+/**
+* RC4 as implemented by OpenSSL
+*/
+class RC4_OpenSSL : public StreamCipher
+ {
+ public:
+ void clear() { clear_mem(&state, 1); }
+
+ std::string name() const;
+ StreamCipher* clone() const { return new RC4_OpenSSL(SKIP); }
+
+ Key_Length_Specification key_spec() const
+ {
+ return Key_Length_Specification(1, 32);
+ }
+
+
+ RC4_OpenSSL(size_t s = 0) : SKIP(s) { clear(); }
+ ~RC4_OpenSSL() { clear(); }
+ private:
+ void cipher(const byte[], byte[], size_t);
+ void key_schedule(const byte[], size_t);
+
+ const size_t SKIP;
+ RC4_KEY state;
+ };
+
+/*
+* Return the name of this type
+*/
+std::string RC4_OpenSSL::name() const
+ {
+ if(SKIP == 0) return "RC4";
+ if(SKIP == 256) return "MARK-4";
+ else return "RC4_skip(" + std::to_string(SKIP) + ")";
+ }
+
+/*
+* RC4 Key Schedule
+*/
+void RC4_OpenSSL::key_schedule(const byte key[], size_t length)
+ {
+ RC4_set_key(&state, length, key);
+ byte dummy = 0;
+ for(size_t i = 0; i != SKIP; ++i)
+ RC4(&state, 1, &dummy, &dummy);
+ }
+
+/*
+* RC4 Encryption
+*/
+void RC4_OpenSSL::cipher(const byte in[], byte out[], size_t length)
+ {
+ RC4(&state, length, in, out);
+ }
+
+}
+
+/**
+* Look for an OpenSSL-supported stream cipher (RC4)
+*/
+StreamCipher*
+OpenSSL_Engine::find_stream_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+ if(request.algo_name() == "RC4")
+ return new RC4_OpenSSL(request.arg_as_integer(0, 0));
+ if(request.algo_name() == "RC4_drop")
+ return new RC4_OpenSSL(768);
+
+ return 0;
+ }
+
+}
diff --git a/lib/engine/openssl/ossl_bc.cpp b/lib/engine/openssl/ossl_bc.cpp
new file mode 100644
index 000000000..b3b509c36
--- /dev/null
+++ b/lib/engine/openssl/ossl_bc.cpp
@@ -0,0 +1,248 @@
+/*
+* OpenSSL Block Cipher
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/openssl_engine.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EVP Block Cipher
+*/
+class EVP_BlockCipher : public BlockCipher
+ {
+ public:
+ void clear();
+ std::string name() const { return cipher_name; }
+ BlockCipher* clone() const;
+
+ size_t block_size() const { return block_sz; }
+
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&);
+
+ EVP_BlockCipher(const EVP_CIPHER*, const std::string&,
+ size_t, size_t, size_t);
+
+ Key_Length_Specification key_spec() const { return cipher_key_spec; }
+
+ ~EVP_BlockCipher();
+ private:
+ void encrypt_n(const byte in[], byte out[], size_t blocks) const;
+ void decrypt_n(const byte in[], byte out[], size_t blocks) const;
+ void key_schedule(const byte[], size_t);
+
+ size_t block_sz;
+ Key_Length_Specification cipher_key_spec;
+ 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) :
+ block_sz(EVP_CIPHER_block_size(algo)),
+ cipher_key_spec(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,
+ size_t key_min, size_t key_max,
+ size_t key_mod) :
+ block_sz(EVP_CIPHER_block_size(algo)),
+ cipher_key_spec(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::encrypt_n(const byte in[], byte out[],
+ size_t blocks) const
+ {
+ int out_len = 0;
+ EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz);
+ }
+
+/*
+* Decrypt a block
+*/
+void EVP_BlockCipher::decrypt_n(const byte in[], byte out[],
+ size_t blocks) const
+ {
+ int out_len = 0;
+ EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz);
+ }
+
+/*
+* Set the key
+*/
+void EVP_BlockCipher::key_schedule(const byte key[], size_t length)
+ {
+ secure_vector<byte> full_key(key, key + length);
+
+ if(cipher_name == "TripleDES" && length == 16)
+ {
+ full_key += std::make_pair(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[0], 0);
+ EVP_DecryptInit_ex(&decrypt, 0, 0, &full_key[0], 0);
+ }
+
+/*
+* Return a clone of this object
+*/
+BlockCipher* EVP_BlockCipher::clone() const
+ {
+ return new EVP_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt),
+ cipher_name,
+ cipher_key_spec.minimum_keylength(),
+ cipher_key_spec.maximum_keylength(),
+ cipher_key_spec.keylength_multiple());
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void EVP_BlockCipher::clear()
+ {
+ 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 SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#define HANDLE_EVP_CIPHER(NAME, EVP) \
+ if(request.algo_name() == NAME && request.arg_count() == 0) \
+ return new EVP_BlockCipher(EVP, NAME);
+
+#define HANDLE_EVP_CIPHER_KEYLEN(NAME, EVP, MIN, MAX, MOD) \
+ if(request.algo_name() == NAME && request.arg_count() == 0) \
+ return new EVP_BlockCipher(EVP, NAME, MIN, MAX, MOD);
+
+#if !defined(OPENSSL_NO_AES)
+ /*
+ Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g
+ cause is unknown
+ */
+ 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());
+#endif
+
+#if !defined(OPENSSL_NO_DES)
+ HANDLE_EVP_CIPHER("DES", EVP_des_ecb());
+ HANDLE_EVP_CIPHER_KEYLEN("TripleDES", EVP_des_ede3_ecb(), 16, 24, 8);
+#endif
+
+#if !defined(OPENSSL_NO_BF)
+ HANDLE_EVP_CIPHER_KEYLEN("Blowfish", EVP_bf_ecb(), 1, 56, 1);
+#endif
+
+#if !defined(OPENSSL_NO_CAST)
+ HANDLE_EVP_CIPHER_KEYLEN("CAST-128", EVP_cast5_ecb(), 1, 16, 1);
+#endif
+
+#if !defined(OPENSSL_NO_CAMELLIA)
+ HANDLE_EVP_CIPHER("Camellia-128", EVP_camellia_128_ecb());
+ HANDLE_EVP_CIPHER("Camellia-192", EVP_camellia_192_ecb());
+ HANDLE_EVP_CIPHER("Camellia-256", EVP_camellia_256_ecb());
+#endif
+
+#if !defined(OPENSSL_NO_RC2)
+ HANDLE_EVP_CIPHER_KEYLEN("RC2", EVP_rc2_ecb(), 1, 32, 1);
+#endif
+
+#if !defined(OPENSSL_NO_RC5) && 0
+ if(request.algo_name() == "RC5")
+ if(request.arg_as_integer(0, 12) == 12)
+ return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb(),
+ "RC5(12)", 1, 32, 1);
+#endif
+
+#if !defined(OPENSSL_NO_IDEA) && 0
+ HANDLE_EVP_CIPHER("IDEA", EVP_idea_ecb());
+#endif
+
+#if !defined(OPENSSL_NO_SEED)
+ HANDLE_EVP_CIPHER("SEED", EVP_seed_ecb());
+#endif
+
+#undef HANDLE_EVP_CIPHER
+#undef HANDLE_EVP_CIPHER_KEYLEN
+
+ return 0;
+ }
+
+}
diff --git a/lib/engine/openssl/ossl_md.cpp b/lib/engine/openssl/ossl_md.cpp
new file mode 100644
index 000000000..e09a68a8e
--- /dev/null
+++ b/lib/engine/openssl/ossl_md.cpp
@@ -0,0 +1,150 @@
+/*
+* OpenSSL Hash Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/openssl_engine.h>
+#include <openssl/evp.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* EVP Hash Function
+*/
+class EVP_HashFunction : public HashFunction
+ {
+ public:
+ void clear();
+ std::string name() const { return algo_name; }
+ HashFunction* clone() const;
+
+ size_t output_length() const
+ {
+ return EVP_MD_size(EVP_MD_CTX_md(&md));
+ }
+
+ size_t hash_block_size() const
+ {
+ return EVP_MD_block_size(EVP_MD_CTX_md(&md));
+ }
+
+ EVP_HashFunction(const EVP_MD*, const std::string&);
+ ~EVP_HashFunction();
+ private:
+ void add_data(const byte[], size_t);
+ 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[], size_t 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()
+ {
+ 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) :
+ 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 SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if !defined(OPENSSL_NO_SHA)
+ if(request.algo_name() == "SHA-160")
+ return new EVP_HashFunction(EVP_sha1(), "SHA-160");
+#endif
+
+#if !defined(OPENSSL_NO_SHA256)
+ if(request.algo_name() == "SHA-224")
+ return new EVP_HashFunction(EVP_sha224(), "SHA-224");
+ if(request.algo_name() == "SHA-256")
+ return new EVP_HashFunction(EVP_sha256(), "SHA-256");
+#endif
+
+#if !defined(OPENSSL_NO_SHA512)
+ if(request.algo_name() == "SHA-384")
+ return new EVP_HashFunction(EVP_sha384(), "SHA-384");
+ if(request.algo_name() == "SHA-512")
+ return new EVP_HashFunction(EVP_sha512(), "SHA-512");
+#endif
+
+#if !defined(OPENSSL_NO_MD2)
+ if(request.algo_name() == "MD2")
+ return new EVP_HashFunction(EVP_md2(), "MD2");
+#endif
+
+#if !defined(OPENSSL_NO_MD4)
+ if(request.algo_name() == "MD4")
+ return new EVP_HashFunction(EVP_md4(), "MD4");
+#endif
+
+#if !defined(OPENSSL_NO_MD5)
+ if(request.algo_name() == "MD5")
+ return new EVP_HashFunction(EVP_md5(), "MD5");
+#endif
+
+#if !defined(OPENSSL_NO_RIPEMD)
+ if(request.algo_name() == "RIPEMD-160")
+ return new EVP_HashFunction(EVP_ripemd160(), "RIPEMD-160");
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/lib/engine/openssl/ossl_pk.cpp b/lib/engine/openssl/ossl_pk.cpp
new file mode 100644
index 000000000..cbe03d7b3
--- /dev/null
+++ b/lib/engine/openssl/ossl_pk.cpp
@@ -0,0 +1,338 @@
+/*
+* OpenSSL PK operations
+* (C) 1999-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/openssl_engine.h>
+#include <botan/internal/bn_wrap.h>
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+ #include <openssl/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+class OSSL_DH_KA_Operation : public PK_Ops::Key_Agreement
+ {
+ public:
+ OSSL_DH_KA_Operation(const DH_PrivateKey& dh) :
+ x(dh.get_x()), p(dh.group_p()) {}
+
+ secure_vector<byte> agree(const byte w[], size_t w_len)
+ {
+ OSSL_BN i(w, w_len), r;
+ BN_mod_exp(r.ptr(), i.ptr(), x.ptr(), p.ptr(), ctx.ptr());
+ return r.to_bytes();
+ }
+
+ private:
+ const OSSL_BN x, p;
+ OSSL_BN_CTX ctx;
+ };
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+
+class OSSL_DSA_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ OSSL_DSA_Signature_Operation(const DSA_PrivateKey& dsa) :
+ x(dsa.get_x()),
+ p(dsa.group_p()),
+ q(dsa.group_q()),
+ g(dsa.group_g()),
+ q_bits(dsa.group_q().bits()) {}
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return (q_bits + 7) / 8; }
+ size_t max_input_bits() const { return q_bits; }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng);
+ private:
+ const OSSL_BN x, p, q, g;
+ const OSSL_BN_CTX ctx;
+ size_t q_bits;
+ };
+
+secure_vector<byte>
+OSSL_DSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator& rng)
+ {
+ const size_t q_bytes = (q_bits + 7) / 8;
+
+ rng.add_entropy(msg, msg_len);
+
+ BigInt k_bn;
+ do
+ k_bn.randomize(rng, q_bits);
+ while(k_bn >= q.to_bigint());
+
+ OSSL_BN i(msg, msg_len);
+ OSSL_BN k(k_bn);
+
+ OSSL_BN r;
+ BN_mod_exp(r.ptr(), g.ptr(), k.ptr(), p.ptr(), ctx.ptr());
+ BN_nnmod(r.ptr(), r.ptr(), q.ptr(), ctx.ptr());
+
+ BN_mod_inverse(k.ptr(), k.ptr(), q.ptr(), ctx.ptr());
+
+ OSSL_BN s;
+ BN_mul(s.ptr(), x.ptr(), r.ptr(), ctx.ptr());
+ BN_add(s.ptr(), s.ptr(), i.ptr());
+ BN_mod_mul(s.ptr(), s.ptr(), k.ptr(), q.ptr(), ctx.ptr());
+
+ if(BN_is_zero(r.ptr()) || BN_is_zero(s.ptr()))
+ throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero");
+
+ secure_vector<byte> output(2*q_bytes);
+ r.encode(&output[0], q_bytes);
+ s.encode(&output[q_bytes], q_bytes);
+ return output;
+ }
+
+class OSSL_DSA_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ OSSL_DSA_Verification_Operation(const DSA_PublicKey& dsa) :
+ y(dsa.get_y()),
+ p(dsa.group_p()),
+ q(dsa.group_q()),
+ g(dsa.group_g()),
+ q_bits(dsa.group_q().bits()) {}
+
+ size_t message_parts() const { return 2; }
+ size_t message_part_size() const { return (q_bits + 7) / 8; }
+ size_t max_input_bits() const { return q_bits; }
+
+ bool with_recovery() const { return false; }
+
+ bool verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len);
+ private:
+ const OSSL_BN y, p, q, g;
+ const OSSL_BN_CTX ctx;
+ size_t q_bits;
+ };
+
+bool OSSL_DSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
+ const byte sig[], size_t sig_len)
+ {
+ const size_t 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.ptr()) || BN_cmp(r.ptr(), q.ptr()) >= 0)
+ return false;
+ if(BN_is_zero(s.ptr()) || BN_cmp(s.ptr(), q.ptr()) >= 0)
+ return false;
+
+ if(BN_mod_inverse(s.ptr(), s.ptr(), q.ptr(), ctx.ptr()) == 0)
+ return false;
+
+ OSSL_BN si;
+ BN_mod_mul(si.ptr(), s.ptr(), i.ptr(), q.ptr(), ctx.ptr());
+ BN_mod_exp(si.ptr(), g.ptr(), si.ptr(), p.ptr(), ctx.ptr());
+
+ OSSL_BN sr;
+ BN_mod_mul(sr.ptr(), s.ptr(), r.ptr(), q.ptr(), ctx.ptr());
+ BN_mod_exp(sr.ptr(), y.ptr(), sr.ptr(), p.ptr(), ctx.ptr());
+
+ BN_mod_mul(si.ptr(), si.ptr(), sr.ptr(), p.ptr(), ctx.ptr());
+ BN_nnmod(si.ptr(), si.ptr(), q.ptr(), ctx.ptr());
+
+ if(BN_cmp(si.ptr(), r.ptr()) == 0)
+ return true;
+ return false;
+
+ return false;
+ }
+
+#endif
+
+#if defined(BOTAN_HAS_RSA)
+
+class OSSL_RSA_Private_Operation : public PK_Ops::Signature,
+ public PK_Ops::Decryption
+ {
+ public:
+ OSSL_RSA_Private_Operation(const RSA_PrivateKey& rsa) :
+ mod(rsa.get_n()),
+ p(rsa.get_p()),
+ q(rsa.get_q()),
+ d1(rsa.get_d1()),
+ d2(rsa.get_d2()),
+ c(rsa.get_c()),
+ n_bits(rsa.get_n().bits())
+ {}
+
+ size_t max_input_bits() const { return (n_bits - 1); }
+
+ secure_vector<byte> sign(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
+ {
+ BigInt m(msg, msg_len);
+ BigInt x = private_op(m);
+ return BigInt::encode_1363(x, (n_bits + 7) / 8);
+ }
+
+ secure_vector<byte> decrypt(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(private_op(m));
+ }
+
+ private:
+ BigInt private_op(const BigInt& m) const;
+
+ const OSSL_BN mod, p, q, d1, d2, c;
+ const OSSL_BN_CTX ctx;
+ size_t n_bits;
+ };
+
+BigInt OSSL_RSA_Private_Operation::private_op(const BigInt& m) const
+ {
+ OSSL_BN j1, j2, h(m);
+
+ BN_mod_exp(j1.ptr(), h.ptr(), d1.ptr(), p.ptr(), ctx.ptr());
+ BN_mod_exp(j2.ptr(), h.ptr(), d2.ptr(), q.ptr(), ctx.ptr());
+ BN_sub(h.ptr(), j1.ptr(), j2.ptr());
+ BN_mod_mul(h.ptr(), h.ptr(), c.ptr(), p.ptr(), ctx.ptr());
+ BN_mul(h.ptr(), h.ptr(), q.ptr(), ctx.ptr());
+ BN_add(h.ptr(), h.ptr(), j2.ptr());
+ return h.to_bigint();
+ }
+
+class OSSL_RSA_Public_Operation : public PK_Ops::Verification,
+ public PK_Ops::Encryption
+ {
+ public:
+ OSSL_RSA_Public_Operation(const RSA_PublicKey& rsa) :
+ n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n())
+ {}
+
+ size_t max_input_bits() const { return (n.bits() - 1); }
+ bool with_recovery() const { return true; }
+
+ secure_vector<byte> encrypt(const byte msg[], size_t msg_len,
+ RandomNumberGenerator&)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_1363(public_op(m), n.bytes());
+ }
+
+ secure_vector<byte> verify_mr(const byte msg[], size_t msg_len)
+ {
+ BigInt m(msg, msg_len);
+ return BigInt::encode_locked(public_op(m));
+ }
+
+ private:
+ BigInt public_op(const BigInt& m) const
+ {
+ if(m >= n)
+ throw Invalid_Argument("RSA public op - input is too large");
+
+ OSSL_BN m_bn(m), r;
+ BN_mod_exp(r.ptr(), m_bn.ptr(), e.ptr(), mod.ptr(), ctx.ptr());
+ return r.to_bigint();
+ }
+
+ const BigInt& n;
+ const OSSL_BN e, mod;
+ const OSSL_BN_CTX ctx;
+ };
+
+#endif
+
+}
+
+PK_Ops::Key_Agreement*
+OpenSSL_Engine::get_key_agreement_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key))
+ return new OSSL_DH_KA_Operation(*dh);
+#endif
+
+ return 0;
+ }
+
+PK_Ops::Signature*
+OpenSSL_Engine::get_signature_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new OSSL_RSA_Private_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key))
+ return new OSSL_DSA_Signature_Operation(*s);
+#endif
+
+ return 0;
+ }
+
+PK_Ops::Verification*
+OpenSSL_Engine::get_verify_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new OSSL_RSA_Public_Operation(*s);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key))
+ return new OSSL_DSA_Verification_Operation(*s);
+#endif
+
+ return 0;
+ }
+
+PK_Ops::Encryption*
+OpenSSL_Engine::get_encryption_op(const Public_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key))
+ return new OSSL_RSA_Public_Operation(*s);
+#endif
+
+ return 0;
+ }
+
+PK_Ops::Decryption*
+OpenSSL_Engine::get_decryption_op(const Private_Key& key, RandomNumberGenerator&) const
+ {
+#if defined(BOTAN_HAS_RSA)
+ if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key))
+ return new OSSL_RSA_Private_Operation(*s);
+#endif
+
+ return 0;
+ }
+
+}
diff --git a/lib/engine/simd_engine/info.txt b/lib/engine/simd_engine/info.txt
new file mode 100644
index 000000000..2063c9dfe
--- /dev/null
+++ b/lib/engine/simd_engine/info.txt
@@ -0,0 +1,15 @@
+define ENGINE_SIMD 20131128
+
+load_on dep
+
+<source>
+simd_engine.cpp
+</source>
+
+<header:internal>
+simd_engine.h
+</header:internal>
+
+<requires>
+simd
+</requires>
diff --git a/lib/engine/simd_engine/simd_engine.cpp b/lib/engine/simd_engine/simd_engine.cpp
new file mode 100644
index 000000000..75463a4b1
--- /dev/null
+++ b/lib/engine/simd_engine/simd_engine.cpp
@@ -0,0 +1,97 @@
+/*
+* SIMD Engine
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/simd_engine.h>
+#include <botan/internal/simd_32.h>
+#include <botan/cpuid.h>
+
+#if defined(BOTAN_HAS_AES_SSSE3)
+ #include <botan/aes_ssse3.h>
+#endif
+
+#if defined(BOTAN_HAS_SERPENT_SIMD)
+ #include <botan/serp_simd.h>
+#endif
+
+#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
+ #include <botan/threefish_avx2.h>
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ #include <botan/noekeon_simd.h>
+#endif
+
+#if defined(BOTAN_HAS_XTEA_SIMD)
+ #include <botan/xtea_simd.h>
+#endif
+
+#if defined(BOTAN_HAS_IDEA_SSE2)
+ #include <botan/idea_sse2.h>
+#endif
+
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ #include <botan/sha1_sse2.h>
+#endif
+
+namespace Botan {
+
+BlockCipher*
+SIMD_Engine::find_block_cipher(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_AES_SSSE3)
+ if(request.algo_name() == "AES-128" && CPUID::has_ssse3())
+ return new AES_128_SSSE3;
+ if(request.algo_name() == "AES-192" && CPUID::has_ssse3())
+ return new AES_192_SSSE3;
+ if(request.algo_name() == "AES-256" && CPUID::has_ssse3())
+ return new AES_256_SSSE3;
+#endif
+
+#if defined(BOTAN_HAS_IDEA_SSE2)
+ if(request.algo_name() == "IDEA" && CPUID::has_sse2())
+ return new IDEA_SSE2;
+#endif
+
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(request.algo_name() == "Noekeon" && SIMD_32::enabled())
+ return new Noekeon_SIMD;
+#endif
+
+#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
+ if(request.algo_name() == "Threefish-512" && CPUID::has_avx2())
+ return new Threefish_512_AVX2;
+#endif
+
+#if defined(BOTAN_HAS_SERPENT_SIMD)
+ if(request.algo_name() == "Serpent" && SIMD_32::enabled())
+ return new Serpent_SIMD;
+#endif
+
+#if defined(BOTAN_HAS_XTEA_SIMD)
+ if(request.algo_name() == "XTEA" && SIMD_32::enabled())
+ return new XTEA_SIMD;
+#endif
+
+ return nullptr;
+ }
+
+HashFunction*
+SIMD_Engine::find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const
+ {
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ if(request.algo_name() == "SHA-160" && CPUID::has_sse2())
+ return new SHA_160_SSE2;
+#endif
+
+ BOTAN_UNUSED(request);
+
+ return nullptr;
+ }
+
+}
diff --git a/lib/engine/simd_engine/simd_engine.h b/lib/engine/simd_engine/simd_engine.h
new file mode 100644
index 000000000..66c8886f1
--- /dev/null
+++ b/lib/engine/simd_engine/simd_engine.h
@@ -0,0 +1,32 @@
+/*
+* SIMD Assembly Engine
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_SIMD_ENGINE_H__
+#define BOTAN_SIMD_ENGINE_H__
+
+#include <botan/engine.h>
+
+namespace Botan {
+
+/**
+* Engine for implementations that use some kind of SIMD
+*/
+class SIMD_Engine : public Engine
+ {
+ public:
+ std::string provider_name() const { return "simd"; }
+
+ BlockCipher* find_block_cipher(const SCAN_Name&,
+ Algorithm_Factory&) const;
+
+ HashFunction* find_hash(const SCAN_Name& request,
+ Algorithm_Factory&) const;
+ };
+
+}
+
+#endif