aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine/openssl/ossl_elg.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-10-08 17:06:18 +0000
committerlloyd <[email protected]>2008-10-08 17:06:18 +0000
commit60e7a9bea4bca8d4c7905129bd98b643da895ed0 (patch)
tree1d1c7e2059d35707001b75f3aff2651915db0a7c /src/engine/openssl/ossl_elg.cpp
parentdf73591726a31a9393be10b2b222dbc45aee87f2 (diff)
Split OpenSSL public key implementations into algorithm specific files,
which allows it to be used while still disabling some (or all) public key algorithms.
Diffstat (limited to 'src/engine/openssl/ossl_elg.cpp')
-rw-r--r--src/engine/openssl/ossl_elg.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/engine/openssl/ossl_elg.cpp b/src/engine/openssl/ossl_elg.cpp
new file mode 100644
index 000000000..25d628ba8
--- /dev/null
+++ b/src/engine/openssl/ossl_elg.cpp
@@ -0,0 +1,93 @@
+/*************************************************
+* OpenSSL Engine Source File *
+* (C) 1999-2007 Jack Lloyd *
+*************************************************/
+
+#include <botan/eng_ossl.h>
+#include <botan/bn_wrap.h>
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090700F
+ #error Your OpenSSL install is too old, upgrade to 0.9.7 or later
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_HAS_ELGAMAL)
+
+namespace {
+
+/*************************************************
+* OpenSSL ElGamal Operation *
+*************************************************/
+class OpenSSL_ELG_Op : public ELG_Operation
+ {
+ public:
+ SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const;
+ BigInt decrypt(const BigInt&, const BigInt&) const;
+
+ ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); }
+ OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1,
+ const BigInt& x1) :
+ x(x1), y(y1), g(group.get_g()), p(group.get_p()) {}
+ private:
+ OSSL_BN x, y, g, p;
+ OSSL_BN_CTX ctx;
+ };
+
+/*************************************************
+* OpenSSL ElGamal Encrypt Operation *
+*************************************************/
+SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length,
+ const BigInt& k_bn) const
+ {
+ OSSL_BN i(in, length);
+
+ if(BN_cmp(i.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large");
+
+ OSSL_BN a, b, k(k_bn);
+
+ BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value);
+ BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value);
+ BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value);
+
+ const u32bit p_bytes = p.bytes();
+ SecureVector<byte> output(2*p_bytes);
+ a.encode(output, p_bytes);
+ b.encode(output + p_bytes, p_bytes);
+ return output;
+ }
+
+/*************************************************
+* OpenSSL ElGamal Decrypt Operation *
+*************************************************/
+BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const
+ {
+ if(BN_is_zero(x.value))
+ throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key");
+
+ OSSL_BN a(a_bn), b(b_bn), t;
+
+ if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0)
+ throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message");
+
+ BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value);
+ BN_mod_inverse(a.value, t.value, p.value, ctx.value);
+ BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value);
+ return a.to_bigint();
+ }
+
+}
+
+/*************************************************
+* Acquire an ElGamal op *
+*************************************************/
+ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y,
+ const BigInt& x) const
+ {
+ return new OpenSSL_ELG_Op(group, y, x);
+ }
+#endif
+
+}