diff options
author | lloyd <[email protected]> | 2008-09-28 15:34:09 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-28 15:34:09 +0000 |
commit | ea32d18231b9c6c5c84b3754c4249170d3b4e4c0 (patch) | |
tree | cc179337d0594ed105768011722b9dbae105e07a /modules/engine/gnump | |
parent | b841401e095cfc1aa0708689d7920eb95ece71af (diff) |
This is the first checkin to net.randombit.botan.modularized, which
has the intent of modularizing Botan's source code, and making it
much easier to add or remove various things at compile time.
In this first checkin:
Add support for nested directories in modules/ and move all the modules
into grouped directories like entropy/ or compression/
Currently this is not ideal, it will _only_ find code in
modules/*/*/modinfo.txt, while it would be much better to allow for
arbitrary nestings under modules (find modules -name modinfo.txt)
for more complicated setups.
This 'new' (OMG I've found directories!) structure allows for a more free
naming convention (no need for leading es_, ml_, etc to group names, though
some keep it for lack of a more meaningful name being obvious to me right
at the moment).
Diffstat (limited to 'modules/engine/gnump')
-rw-r--r-- | modules/engine/gnump/eng_gmp.cpp | 377 | ||||
-rw-r--r-- | modules/engine/gnump/eng_gmp.h | 43 | ||||
-rw-r--r-- | modules/engine/gnump/gmp_mem.cpp | 60 | ||||
-rw-r--r-- | modules/engine/gnump/gmp_powm.cpp | 51 | ||||
-rw-r--r-- | modules/engine/gnump/gmp_wrap.cpp | 96 | ||||
-rw-r--r-- | modules/engine/gnump/gmp_wrap.h | 36 | ||||
-rw-r--r-- | modules/engine/gnump/modinfo.txt | 18 |
7 files changed, 681 insertions, 0 deletions
diff --git a/modules/engine/gnump/eng_gmp.cpp b/modules/engine/gnump/eng_gmp.cpp new file mode 100644 index 000000000..a0e18e059 --- /dev/null +++ b/modules/engine/gnump/eng_gmp.cpp @@ -0,0 +1,377 @@ +/************************************************* +* GMP Engine Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/eng_gmp.h> +#include <botan/gmp_wrap.h> +#include <gmp.h> + +namespace Botan { + +namespace { + +/************************************************* +* GMP IF Operation * +*************************************************/ +class GMP_IF_Op : public IF_Operation + { + public: + BigInt public_op(const BigInt&) const; + BigInt private_op(const BigInt&) const; + + IF_Operation* clone() const { return new GMP_IF_Op(*this); } + + GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&, + const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn, + const BigInt& d2_bn, const BigInt& c_bn) : + e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {} + private: + const GMP_MPZ e, n, p, q, d1, d2, c; + }; + +/************************************************* +* GMP IF Public Operation * +*************************************************/ +BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const + { + GMP_MPZ i(i_bn); + mpz_powm(i.value, i.value, e.value, n.value); + return i.to_bigint(); + } + +/************************************************* +* GMP IF Private Operation * +*************************************************/ +BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const + { + if(mpz_cmp_ui(p.value, 0) == 0) + throw Internal_Error("GMP_IF_Op::private_op: No private key"); + + GMP_MPZ j1, j2, h(i_bn); + + mpz_powm(j1.value, h.value, d1.value, p.value); + mpz_powm(j2.value, h.value, d2.value, q.value); + mpz_sub(h.value, j1.value, j2.value); + mpz_mul(h.value, h.value, c.value); + mpz_mod(h.value, h.value, p.value); + mpz_mul(h.value, h.value, q.value); + mpz_add(h.value, h.value, j2.value); + return h.to_bigint(); + } + +/************************************************* +* GMP DSA Operation * +*************************************************/ +class GMP_DSA_Op : public DSA_Operation + { + public: + bool verify(const byte[], u32bit, const byte[], u32bit) const; + SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; + + DSA_Operation* clone() const { return new GMP_DSA_Op(*this); } + + GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : + x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} + private: + const GMP_MPZ x, y, p, q, g; + }; + +/************************************************* +* GMP DSA Verify Operation * +*************************************************/ +bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) const + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes || msg_len > q_bytes) + return false; + + GMP_MPZ r(sig, q_bytes); + GMP_MPZ s(sig + q_bytes, q_bytes); + GMP_MPZ i(msg, msg_len); + + if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0) + return false; + if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0) + return false; + + if(mpz_invert(s.value, s.value, q.value) == 0) + return false; + + GMP_MPZ si; + mpz_mul(si.value, s.value, i.value); + mpz_mod(si.value, si.value, q.value); + mpz_powm(si.value, g.value, si.value, p.value); + + GMP_MPZ sr; + mpz_mul(sr.value, s.value, r.value); + mpz_mod(sr.value, sr.value, q.value); + mpz_powm(sr.value, y.value, sr.value, p.value); + + mpz_mul(si.value, si.value, sr.value); + mpz_mod(si.value, si.value, p.value); + mpz_mod(si.value, si.value, q.value); + + if(mpz_cmp(si.value, r.value) == 0) + return true; + return false; + } + +/************************************************* +* GMP DSA Sign Operation * +*************************************************/ +SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length, + const BigInt& k_bn) const + { + if(mpz_cmp_ui(x.value, 0) == 0) + throw Internal_Error("GMP_DSA_Op::sign: No private key"); + + GMP_MPZ i(in, length); + GMP_MPZ k(k_bn); + + GMP_MPZ r; + mpz_powm(r.value, g.value, k.value, p.value); + mpz_mod(r.value, r.value, q.value); + + mpz_invert(k.value, k.value, q.value); + + GMP_MPZ s; + mpz_mul(s.value, x.value, r.value); + mpz_add(s.value, s.value, i.value); + mpz_mul(s.value, s.value, k.value); + mpz_mod(s.value, s.value, q.value); + + if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0) + throw Internal_Error("GMP_DSA_Op::sign: r or s was zero"); + + const u32bit q_bytes = q.bytes(); + + SecureVector<byte> output(2*q_bytes); + r.encode(output, q_bytes); + s.encode(output + q_bytes, q_bytes); + return output; + } + +/************************************************* +* GMP NR Operation * +*************************************************/ +class GMP_NR_Op : public NR_Operation + { + public: + SecureVector<byte> verify(const byte[], u32bit) const; + SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; + + NR_Operation* clone() const { return new GMP_NR_Op(*this); } + + GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : + x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} + private: + const GMP_MPZ x, y, p, q, g; + }; + +/************************************************* +* GMP NR Verify Operation * +*************************************************/ +SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes) + return false; + + GMP_MPZ c(sig, q_bytes); + GMP_MPZ d(sig + q_bytes, q_bytes); + + if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 || + mpz_cmp(d.value, q.value) >= 0) + throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature"); + + GMP_MPZ i1, i2; + mpz_powm(i1.value, g.value, d.value, p.value); + mpz_powm(i2.value, y.value, c.value, p.value); + mpz_mul(i1.value, i1.value, i2.value); + mpz_mod(i1.value, i1.value, p.value); + mpz_sub(i1.value, c.value, i1.value); + mpz_mod(i1.value, i1.value, q.value); + return BigInt::encode(i1.to_bigint()); + } + +/************************************************* +* GMP NR Sign Operation * +*************************************************/ +SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length, + const BigInt& k_bn) const + { + if(mpz_cmp_ui(x.value, 0) == 0) + throw Internal_Error("GMP_NR_Op::sign: No private key"); + + GMP_MPZ f(in, length); + GMP_MPZ k(k_bn); + + if(mpz_cmp(f.value, q.value) >= 0) + throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range"); + + GMP_MPZ c, d; + mpz_powm(c.value, g.value, k.value, p.value); + mpz_add(c.value, c.value, f.value); + mpz_mod(c.value, c.value, q.value); + mpz_mul(d.value, x.value, c.value); + mpz_sub(d.value, k.value, d.value); + mpz_mod(d.value, d.value, q.value); + + if(mpz_cmp_ui(c.value, 0) == 0) + throw Internal_Error("Default_NR_Op::sign: c was zero"); + + const u32bit q_bytes = q.bytes(); + SecureVector<byte> output(2*q_bytes); + c.encode(output, q_bytes); + d.encode(output + q_bytes, q_bytes); + return output; + } + +/************************************************* +* GMP ElGamal Operation * +*************************************************/ +class GMP_ELG_Op : public ELG_Operation + { + public: + SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; + BigInt decrypt(const BigInt&, const BigInt&) const; + + ELG_Operation* clone() const { return new GMP_ELG_Op(*this); } + + GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : + x(x1), y(y1), g(group.get_g()), p(group.get_p()) {} + private: + GMP_MPZ x, y, g, p; + }; + +/************************************************* +* GMP ElGamal Encrypt Operation * +*************************************************/ +SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length, + const BigInt& k_bn) const + { + GMP_MPZ i(in, length); + + if(mpz_cmp(i.value, p.value) >= 0) + throw Invalid_Argument("GMP_ELG_Op: Input is too large"); + + GMP_MPZ a, b, k(k_bn); + + mpz_powm(a.value, g.value, k.value, p.value); + mpz_powm(b.value, y.value, k.value, p.value); + mpz_mul(b.value, b.value, i.value); + mpz_mod(b.value, b.value, p.value); + + const u32bit p_bytes = p.bytes(); + SecureVector<byte> output(2*p_bytes); + a.encode(output, p_bytes); + b.encode(output + p_bytes, p_bytes); + return output; + } + +/************************************************* +* GMP ElGamal Decrypt Operation * +*************************************************/ +BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const + { + if(mpz_cmp_ui(x.value, 0) == 0) + throw Internal_Error("GMP_ELG_Op::decrypt: No private key"); + + GMP_MPZ a(a_bn), b(b_bn); + + if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0) + throw Invalid_Argument("GMP_ELG_Op: Invalid message"); + + mpz_powm(a.value, a.value, x.value, p.value); + mpz_invert(a.value, a.value, p.value); + mpz_mul(a.value, a.value, b.value); + mpz_mod(a.value, a.value, p.value); + return a.to_bigint(); + } + +/************************************************* +* GMP DH Operation * +*************************************************/ +class GMP_DH_Op : public DH_Operation + { + public: + BigInt agree(const BigInt& i) const; + DH_Operation* clone() const { return new GMP_DH_Op(*this); } + + GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) : + x(x_bn), p(group.get_p()) {} + private: + GMP_MPZ x, p; + }; + +/************************************************* +* GMP DH Key Agreement Operation * +*************************************************/ +BigInt GMP_DH_Op::agree(const BigInt& i_bn) const + { + GMP_MPZ i(i_bn); + mpz_powm(i.value, i.value, x.value, p.value); + return i.to_bigint(); + } + +} + +/************************************************* +* GMP_Engine Constructor * +*************************************************/ +GMP_Engine::GMP_Engine() + { + set_memory_hooks(); + } + +/************************************************* +* Acquire an IF op * +*************************************************/ +IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n, + const BigInt& d, const BigInt& p, + const BigInt& q, const BigInt& d1, + const BigInt& d2, const BigInt& c) const + { + return new GMP_IF_Op(e, n, d, p, q, d1, d2, c); + } + +/************************************************* +* Acquire a DSA op * +*************************************************/ +DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y, + const BigInt& x) const + { + return new GMP_DSA_Op(group, y, x); + } + +/************************************************* +* Acquire a NR op * +*************************************************/ +NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y, + const BigInt& x) const + { + return new GMP_NR_Op(group, y, x); + } + +/************************************************* +* Acquire an ElGamal op * +*************************************************/ +ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y, + const BigInt& x) const + { + return new GMP_ELG_Op(group, y, x); + } + +/************************************************* +* Acquire a DH op * +*************************************************/ +DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const + { + return new GMP_DH_Op(group, x); + } + +} diff --git a/modules/engine/gnump/eng_gmp.h b/modules/engine/gnump/eng_gmp.h new file mode 100644 index 000000000..2ac2b54a8 --- /dev/null +++ b/modules/engine/gnump/eng_gmp.h @@ -0,0 +1,43 @@ +/************************************************* +* GMP Engine Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_EXT_ENGINE_GMP_H__ +#define BOTAN_EXT_ENGINE_GMP_H__ + +#include <botan/engine.h> + +namespace Botan { + +/************************************************* +* GMP Engine * +*************************************************/ +class GMP_Engine : public Engine + { + public: + IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, + const BigInt&, const BigInt&, const BigInt&, + const BigInt&, const BigInt&) const; + + DSA_Operation* dsa_op(const DL_Group&, const BigInt&, + const BigInt&) const; + + NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; + + ELG_Operation* elg_op(const DL_Group&, const BigInt&, + const BigInt&) const; + + DH_Operation* dh_op(const DL_Group&, const BigInt&) const; + + Modular_Exponentiator* mod_exp(const BigInt&, + Power_Mod::Usage_Hints) const; + + GMP_Engine(); + private: + static void set_memory_hooks(); + }; + +} + +#endif diff --git a/modules/engine/gnump/gmp_mem.cpp b/modules/engine/gnump/gmp_mem.cpp new file mode 100644 index 000000000..ea8ef4d3b --- /dev/null +++ b/modules/engine/gnump/gmp_mem.cpp @@ -0,0 +1,60 @@ +/************************************************* +* GNU MP Memory Handlers Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/eng_gmp.h> +#include <cstring> +#include <gmp.h> + +namespace Botan { + +namespace { + +/************************************************* +* Allocator used by GNU MP * +*************************************************/ +Allocator* gmp_alloc = 0; + +/************************************************* +* Allocation Function for GNU MP * +*************************************************/ +void* gmp_malloc(size_t n) + { + return gmp_alloc->allocate(n); + } + +/************************************************* +* Reallocation Function for GNU MP * +*************************************************/ +void* gmp_realloc(void* ptr, size_t old_n, size_t new_n) + { + void* new_buf = gmp_alloc->allocate(new_n); + std::memcpy(new_buf, ptr, std::min(old_n, new_n)); + gmp_alloc->deallocate(ptr, old_n); + return new_buf; + } + +/************************************************* +* Deallocation Function for GNU MP * +*************************************************/ +void gmp_free(void* ptr, size_t n) + { + gmp_alloc->deallocate(ptr, n); + } + +} + +/************************************************* +* Set the GNU MP memory functions * +*************************************************/ +void GMP_Engine::set_memory_hooks() + { + if(gmp_alloc == 0) + { + gmp_alloc = Allocator::get(true); + mp_set_memory_functions(gmp_malloc, gmp_realloc, gmp_free); + } + } + +} diff --git a/modules/engine/gnump/gmp_powm.cpp b/modules/engine/gnump/gmp_powm.cpp new file mode 100644 index 000000000..a5e3d1c0d --- /dev/null +++ b/modules/engine/gnump/gmp_powm.cpp @@ -0,0 +1,51 @@ +/************************************************* +* GMP Modular Exponentiation Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/eng_gmp.h> +#include <botan/gmp_wrap.h> + +namespace Botan { + +namespace { + +/************************************************* +* GMP Modular Exponentiator * +*************************************************/ +class GMP_Modular_Exponentiator : public Modular_Exponentiator + { + public: + void set_base(const BigInt& b) { base = b; } + void set_exponent(const BigInt& e) { exp = e; } + BigInt execute() const; + Modular_Exponentiator* copy() const + { return new GMP_Modular_Exponentiator(*this); } + + GMP_Modular_Exponentiator(const BigInt& n) : mod(n) {} + private: + GMP_MPZ base, exp, mod; + }; + +/************************************************* +* Compute the result * +*************************************************/ +BigInt GMP_Modular_Exponentiator::execute() const + { + GMP_MPZ r; + mpz_powm(r.value, base.value, exp.value, mod.value); + return r.to_bigint(); + } + +} + +/************************************************* +* Return the GMP-based modular exponentiator * +*************************************************/ +Modular_Exponentiator* GMP_Engine::mod_exp(const BigInt& n, + Power_Mod::Usage_Hints) const + { + return new GMP_Modular_Exponentiator(n); + } + +} diff --git a/modules/engine/gnump/gmp_wrap.cpp b/modules/engine/gnump/gmp_wrap.cpp new file mode 100644 index 000000000..4c73c2562 --- /dev/null +++ b/modules/engine/gnump/gmp_wrap.cpp @@ -0,0 +1,96 @@ +/************************************************* +* GMP Wrapper Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/gmp_wrap.h> + +#define GNU_MP_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c)) + +#define GNU_MP_VERSION_CODE \ + GNU_MP_VERSION_CODE_FOR(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, \ + __GNU_MP_VERSION_PATCHLEVEL) + +#if GNU_MP_VERSION_CODE < GNU_MP_VERSION_CODE_FOR(4,1,0) + #error Your GNU MP install is too old, upgrade to 4.1 or later +#endif + +namespace Botan { + +/************************************************* +* GMP_MPZ Constructor * +*************************************************/ +GMP_MPZ::GMP_MPZ(const BigInt& in) + { + mpz_init(value); + if(in != 0) + mpz_import(value, in.sig_words(), -1, sizeof(word), 0, 0, in.data()); + } + +/************************************************* +* GMP_MPZ Constructor * +*************************************************/ +GMP_MPZ::GMP_MPZ(const byte in[], u32bit length) + { + mpz_init(value); + mpz_import(value, length, 1, 1, 0, 0, in); + } + +/************************************************* +* GMP_MPZ Copy Constructor * +*************************************************/ +GMP_MPZ::GMP_MPZ(const GMP_MPZ& other) + { + mpz_init_set(value, other.value); + } + +/************************************************* +* GMP_MPZ Destructor * +*************************************************/ +GMP_MPZ::~GMP_MPZ() + { + mpz_clear(value); + } + +/************************************************* +* GMP_MPZ Assignment Operator * +*************************************************/ +GMP_MPZ& GMP_MPZ::operator=(const GMP_MPZ& other) + { + mpz_set(value, other.value); + return (*this); + } + +/************************************************* +* Export the mpz_t as a bytestring * +*************************************************/ +void GMP_MPZ::encode(byte out[], u32bit length) const + { + size_t dummy = 0; + mpz_export(out + (length - bytes()), &dummy, 1, 1, 0, 0, value); + } + +/************************************************* +* Return the number of significant bytes * +*************************************************/ +u32bit GMP_MPZ::bytes() const + { + return ((mpz_sizeinbase(value, 2) + 7) / 8); + } + +/************************************************* +* GMP to BigInt Conversions * +*************************************************/ +BigInt GMP_MPZ::to_bigint() const + { + BigInt out(BigInt::Positive, (bytes() + sizeof(word) - 1) / sizeof(word)); + size_t dummy = 0; + mpz_export(out.get_reg(), &dummy, -1, sizeof(word), 0, 0, value); + + if(mpz_sgn(value) < 0) + out.flip_sign(); + + return out; + } + +} diff --git a/modules/engine/gnump/gmp_wrap.h b/modules/engine/gnump/gmp_wrap.h new file mode 100644 index 000000000..0da54550f --- /dev/null +++ b/modules/engine/gnump/gmp_wrap.h @@ -0,0 +1,36 @@ +/************************************************* +* GMP MPZ Wrapper Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_EXT_GMP_MPZ_WRAP_H__ +#define BOTAN_EXT_GMP_MPZ_WRAP_H__ + +#include <botan/bigint.h> +#include <gmp.h> + +namespace Botan { + +/************************************************* +* Lightweight GMP mpz_t Wrapper * +*************************************************/ +class GMP_MPZ + { + public: + mpz_t value; + + BigInt to_bigint() const; + void encode(byte[], u32bit) const; + u32bit bytes() const; + + GMP_MPZ& operator=(const GMP_MPZ&); + + GMP_MPZ(const GMP_MPZ&); + GMP_MPZ(const BigInt& = 0); + GMP_MPZ(const byte[], u32bit); + ~GMP_MPZ(); + }; + +} + +#endif diff --git a/modules/engine/gnump/modinfo.txt b/modules/engine/gnump/modinfo.txt new file mode 100644 index 000000000..e65e411fd --- /dev/null +++ b/modules/engine/gnump/modinfo.txt @@ -0,0 +1,18 @@ +realname "GMP Engine" + +define ENGINE_GNU_MP + +load_on request + +<add> +eng_gmp.cpp +gmp_wrap.cpp +gmp_mem.cpp +gmp_powm.cpp +eng_gmp.h +gmp_wrap.h +</add> + +<libs> +all -> gmp +</libs> |