summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/BigInt.cc378
1 files changed, 378 insertions, 0 deletions
diff --git a/src/BigInt.cc b/src/BigInt.cc
new file mode 100644
index 0000000..7a30e7e
--- /dev/null
+++ b/src/BigInt.cc
@@ -0,0 +1,378 @@
+#include <malloc.h>
+#include <math.h>
+#include "tomcrypt.h"
+#include "BigInt.h"
+#include "Main.h"
+
+namespace {
+
+class InitMP : public Balau::AtStart {
+ public:
+ InitMP() : AtStart(0) { }
+ void doStart() {
+ ltc_mp = ltm_desc;
+ m_initialized = true;
+ static Balau::BigInt s2p32;
+ IAssert(!m_2p32, "doStart should only be called once.");
+ s2p32.set2expt(32);
+ m_2p32 = &s2p32;
+ }
+ const Balau::BigInt & get2p32() {
+ return *m_2p32;
+ }
+ bool initialized() { return m_initialized; }
+ private:
+ Balau::BigInt * m_2p32 = NULL;
+ bool m_initialized = false;
+};
+
+static InitMP s_MP;
+
+};
+
+Balau::BigInt::BigInt() throw (GeneralException) {
+ AAssert(s_MP.initialized(), "You can't statically declare a BigInt.");
+ if (mp_init(&m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_init");
+}
+
+Balau::BigInt::BigInt(const BigInt & v) throw (GeneralException) {
+ AAssert(s_MP.initialized(), "You can't statically declare a BigInt.");
+ if (mp_init_copy(&m_bi, v.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_init_copy");
+}
+
+Balau::BigInt::BigInt(BigInt && v) {
+ m_bi = v.m_bi;
+ v.m_bi = NULL;
+}
+
+Balau::BigInt::~BigInt() {
+ if (!m_bi)
+ return;
+ mp_clear(m_bi);
+ m_bi = NULL;
+}
+
+Balau::BigInt & Balau::BigInt::operator=(const BigInt & v) throw (GeneralException) {
+ if (&v == this)
+ return *this;
+
+ if (mp_copy(v.m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_init_copy");
+}
+
+void Balau::BigInt::set(uint64_t v) throw (GeneralException) {
+ uint32_t low = v & 0xffffffff;
+ uint32_t high = v >> 32;
+ if (high == 0) {
+ if (mp_set_int(m_bi, low) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_set_init");
+ } else {
+ if (mp_set_int(m_bi, high) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_set_init");
+ operator*=(s_MP.get2p32());
+ operator+=(low);
+ }
+}
+
+void Balau::BigInt::set(int64_t v) {
+ if (v >= 0) {
+ set((uint64_t) v);
+ } else {
+ v = -v;
+ set((uint64_t) v);
+ neg();
+ }
+}
+
+void Balau::BigInt::set(uint32_t v) throw (GeneralException) {
+ if (mp_set_int(m_bi, v) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_set_init");
+}
+
+void Balau::BigInt::set(int32_t v) {
+ if (v >= 0) {
+ set((uint32_t) v);
+ } else {
+ v = -v;
+ set((uint32_t) v);
+ neg();
+ }
+}
+
+void Balau::BigInt::set(double v) throw (GeneralException) {
+ double f, i;
+ f = modf(v, &i);
+ AAssert(f == 0.0, "Can't set a BigInt with a double that has a fractional value");
+
+ int e;
+
+ f = frexp(v, &e);
+ if (mp_set_int(m_bi, 0) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_set_init");
+
+ for (e -= 1.0; e > 0.0; e -= 1.0) {
+ f *= 2.0;
+ if (f >= 1.0) {
+ operator+=(1);
+ f -= 1.0;
+ }
+ operator*=(2);
+ }
+}
+
+void Balau::BigInt::set(const String & v, int radix) throw (GeneralException) {
+ if (mp_read_radix(m_bi, v.to_charp(), radix) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_read_radix");
+}
+
+void Balau::BigInt::set2expt(int i) throw (GeneralException) {
+ if (mp_2expt(m_bi, i) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_2expt");
+}
+
+Balau::BigInt Balau::BigInt::operator+(unsigned int i) const throw (GeneralException) {
+ BigInt r;
+ if (mp_add_d(m_bi, i, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_add_d");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator+(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_add(m_bi, a.m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_add");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator-(unsigned int i) const throw (GeneralException) {
+ BigInt r;
+ if (mp_sub_d(m_bi, i, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sub_d");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator-(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_sub(m_bi, a.m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sub");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator*(unsigned int i) const throw (GeneralException) {
+ BigInt r;
+ if (mp_mul_d(m_bi, i, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_mul_d");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator*(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_mul(m_bi, a.m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_mul");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator/(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_div(m_bi, a.m_bi, r.m_bi, NULL) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator%(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_div(m_bi, a.m_bi, NULL, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::operator<<(unsigned int a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_mul_d(m_bi, 1 << a, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return *this;
+}
+
+Balau::BigInt Balau::BigInt::operator>>(unsigned int a) const {
+ BigInt s;
+ s.set2expt(a);
+ return operator/(s);
+}
+
+Balau::BigInt & Balau::BigInt::operator+=(unsigned int i) throw (GeneralException) {
+ if (mp_add_d(m_bi, i, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_add_d");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator+=(const BigInt & a) throw (GeneralException) {
+ if (mp_add(m_bi, a.m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_add");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator-=(unsigned int i) throw (GeneralException) {
+ if (mp_sub_d(m_bi, i, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sub_d");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator-=(const BigInt & a) throw (GeneralException) {
+ if (mp_sub(m_bi, a.m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sub");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator*=(unsigned int i) throw (GeneralException) {
+ if (mp_mul_d(m_bi, i, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_mul_d");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator*=(const BigInt & a) throw (GeneralException) {
+ if (mp_mul(m_bi, a.m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_mul");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator/=(const BigInt & a) throw (GeneralException) {
+ if (mp_div(m_bi, a.m_bi, m_bi, NULL) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator%=(const BigInt & a) throw (GeneralException) {
+ if (mp_div(m_bi, a.m_bi, NULL, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator<<=(unsigned int a) throw (GeneralException) {
+ if (mp_mul_d(m_bi, 1 << a, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_div");
+ return *this;
+}
+
+Balau::BigInt & Balau::BigInt::operator>>=(unsigned int a) {
+ BigInt s;
+ s.set2expt(a);
+ return operator/=(s);
+}
+
+Balau::BigInt Balau::BigInt::operator-() const throw (GeneralException) {
+ BigInt r(*this);
+ r.neg();
+ return r;
+}
+
+Balau::BigInt & Balau::BigInt::operator++() {
+ operator+=(1);
+ return *this;
+}
+
+Balau::BigInt Balau::BigInt::operator++(int) {
+ BigInt r(*this);
+ operator+=(1);
+ return r;
+}
+
+Balau::BigInt & Balau::BigInt::operator--() {
+ operator-=(1);
+ return *this;
+}
+
+Balau::BigInt Balau::BigInt::operator--(int) {
+ BigInt r(*this);
+ operator-=(1);
+ return r;
+}
+
+Balau::BigInt & Balau::BigInt::neg() throw (GeneralException) {
+ if (mp_neg(m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_neg");
+}
+
+Balau::BigInt Balau::BigInt::sqrt() const throw (GeneralException) {
+ BigInt r;
+ if (mp_sqr(m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sqr");
+ return r;
+}
+
+Balau::BigInt & Balau::BigInt::do_sqrt() throw (GeneralException) {
+ if (mp_sqr(m_bi, m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_sqr");
+ return *this;
+}
+
+Balau::BigInt Balau::BigInt::gcd(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_gcd(m_bi, a.m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_gcd");
+ return r;
+}
+
+Balau::BigInt Balau::BigInt::lcm(const BigInt & a) const throw (GeneralException) {
+ BigInt r;
+ if (mp_lcm(m_bi, a.m_bi, r.m_bi) != CRYPT_OK)
+ throw GeneralException("Error while calling mp_lcm");
+ return r;
+}
+
+Balau::BigInt::comp_t Balau::BigInt::comp(const BigInt & a) const throw (GeneralException) {
+ int r = mp_cmp(m_bi, a.m_bi);
+ switch (r) {
+ case LTC_MP_LT:
+ return LT;
+ case LTC_MP_GT:
+ return GT;
+ case LTC_MP_EQ:
+ return EQ;
+ default:
+ throw GeneralException("Unknown result from mp_cmp");
+ }
+}
+
+bool Balau::BigInt::operator==(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r == EQ;
+}
+
+bool Balau::BigInt::operator!=(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r != EQ;
+}
+
+bool Balau::BigInt::operator<=(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r == LT || r == EQ;
+}
+
+bool Balau::BigInt::operator>=(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r == GT || r == EQ;
+}
+
+bool Balau::BigInt::operator<(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r == LT;
+}
+
+bool Balau::BigInt::operator>(const BigInt & a) const {
+ comp_t r = comp(a);
+ return r == GT;
+}
+
+Balau::String Balau::BigInt::toString(int radix) const {
+ char * out = (char *) alloca(mp_count_bits(m_bi) / (radix >= 10 ? 3 : 1) + 3);
+ mp_toradix(m_bi, out, radix);
+ return String(out);
+}
+
+char * Balau::BigInt::makeString(int radix) const {
+ char * out = (char *) malloc(mp_count_bits(m_bi) / (radix >= 10 ? 3 : 1) + 3);
+ mp_toradix(m_bi, out, radix);
+ return out;
+}