aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/math
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-04-23 19:01:51 -0400
committerJack Lloyd <[email protected]>2018-04-23 19:33:06 -0400
commitd1479ede7bc01b60f67d6826611baf43987e941b (patch)
tree86deee3c166871aa58039c857196f2ef6be6b5e9 /src/lib/math
parentc90d868a533c13501e8d6e3b71919501b9d70f9e (diff)
Add BigInt::mod_sub
Diffstat (limited to 'src/lib/math')
-rw-r--r--src/lib/math/bigint/big_ops2.cpp49
-rw-r--r--src/lib/math/bigint/bigint.h16
2 files changed, 65 insertions, 0 deletions
diff --git a/src/lib/math/bigint/big_ops2.cpp b/src/lib/math/bigint/big_ops2.cpp
index 212a44fa0..242635257 100644
--- a/src/lib/math/bigint/big_ops2.cpp
+++ b/src/lib/math/bigint/big_ops2.cpp
@@ -95,6 +95,55 @@ BigInt& BigInt::operator-=(const BigInt& y)
return (*this);
}
+BigInt& BigInt::mod_add(const BigInt& s, const BigInt& mod, secure_vector<word>& ws)
+ {
+ if(this->is_negative() || s.is_negative() || mod.is_negative())
+ throw Invalid_Argument("BigInt::mod_add expects all arguments are positive");
+
+ // TODO add optimized version of this
+ *this += s;
+ this->reduce_below(mod, ws);
+
+ return (*this);
+ }
+
+BigInt& BigInt::mod_sub(const BigInt& s, const BigInt& mod, secure_vector<word>& ws)
+ {
+ if(this->is_negative() || s.is_negative() || mod.is_negative())
+ throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
+
+ const size_t t_sw = sig_words();
+ const size_t s_sw = s.sig_words();
+ const size_t mod_sw = mod.sig_words();
+
+ if(t_sw > mod_sw || s_sw > mod_sw)
+ throw Invalid_Argument("BigInt::mod_sub args larger than modulus");
+
+ int32_t relative_size = bigint_cmp(data(), t_sw, s.data(), s_sw);
+
+ if(relative_size >= 0)
+ {
+ // this >= s in which case just subtract
+ bigint_sub2(mutable_data(), t_sw, s.data(), s_sw);
+ }
+ else
+ {
+ // Otherwise we must sub s and then add p (or add (p - s) as here)
+
+ ws.resize(mod_sw + 1);
+
+ bigint_sub3(ws.data(), mod.data(), mod_sw, s.data(), s_sw);
+
+ if(m_reg.size() < mod_sw)
+ grow_to(mod_sw);
+
+ word carry = bigint_add2_nc(mutable_data(), m_reg.size(), ws.data(), mod_sw);
+ BOTAN_ASSERT_NOMSG(carry == 0);
+ }
+
+ return (*this);
+ }
+
BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws)
{
/*
diff --git a/src/lib/math/bigint/bigint.h b/src/lib/math/bigint/bigint.h
index eec7f6176..bb7a69541 100644
--- a/src/lib/math/bigint/bigint.h
+++ b/src/lib/math/bigint/bigint.h
@@ -266,6 +266,22 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
BigInt& rev_sub(const word y[], size_t y_size, secure_vector<word>& ws);
/**
+ * Set *this to (*this + y) % mod
+ * @param y the BigInt to add - assumed y >= 0 and y < mod
+ * @param mod the positive modulus
+ * @param ws a temp workspace
+ */
+ BigInt& mod_add(const BigInt& y, const BigInt& mod, secure_vector<word>& ws);
+
+ /**
+ * Set *this to (*this - y) % mod
+ * @param y the BigInt to subtract - assumed y >= 0 and y < mod
+ * @param mod the positive modulus
+ * @param ws a temp workspace
+ */
+ BigInt& mod_sub(const BigInt& y, const BigInt& mod, secure_vector<word>& ws);
+
+ /**
* Return *this below mod
*
* Assumes that *this is (if anything) only slightly larger than