diff options
author | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
commit | 6894dca64c04936d07048c0e8cbf7e25858548c3 (patch) | |
tree | 5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/engine/gnump | |
parent | 9efa3be92442afb3d0b69890a36c7f122df18eda (diff) |
Move lib into src
Diffstat (limited to 'src/lib/engine/gnump')
-rw-r--r-- | src/lib/engine/gnump/gmp_mem.cpp | 83 | ||||
-rw-r--r-- | src/lib/engine/gnump/gmp_powm.cpp | 53 | ||||
-rw-r--r-- | src/lib/engine/gnump/gmp_wrap.cpp | 101 | ||||
-rw-r--r-- | src/lib/engine/gnump/gmp_wrap.h | 41 | ||||
-rw-r--r-- | src/lib/engine/gnump/gnump_engine.h | 44 | ||||
-rw-r--r-- | src/lib/engine/gnump/gnump_pk.cpp | 338 | ||||
-rw-r--r-- | src/lib/engine/gnump/info.txt | 23 |
7 files changed, 683 insertions, 0 deletions
diff --git a/src/lib/engine/gnump/gmp_mem.cpp b/src/lib/engine/gnump/gmp_mem.cpp new file mode 100644 index 000000000..b5a5a303e --- /dev/null +++ b/src/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/src/lib/engine/gnump/gmp_powm.cpp b/src/lib/engine/gnump/gmp_powm.cpp new file mode 100644 index 000000000..70c2b2f5e --- /dev/null +++ b/src/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/src/lib/engine/gnump/gmp_wrap.cpp b/src/lib/engine/gnump/gmp_wrap.cpp new file mode 100644 index 000000000..974593d02 --- /dev/null +++ b/src/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/src/lib/engine/gnump/gmp_wrap.h b/src/lib/engine/gnump/gmp_wrap.h new file mode 100644 index 000000000..291d65a01 --- /dev/null +++ b/src/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/src/lib/engine/gnump/gnump_engine.h b/src/lib/engine/gnump/gnump_engine.h new file mode 100644 index 000000000..ccc723514 --- /dev/null +++ b/src/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/src/lib/engine/gnump/gnump_pk.cpp b/src/lib/engine/gnump/gnump_pk.cpp new file mode 100644 index 000000000..29e172d47 --- /dev/null +++ b/src/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/src/lib/engine/gnump/info.txt b/src/lib/engine/gnump/info.txt new file mode 100644 index 000000000..ad03339e4 --- /dev/null +++ b/src/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> |