aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-12-01 14:05:24 -0500
committerJack Lloyd <[email protected]>2018-12-01 14:05:24 -0500
commit931302e2457ef90b3b3b7dacdeeee2b143bfee66 (patch)
tree0b2607f4193a899c4012e3072f4a71e9d17128e4
parent1e9e5d2f3bdac32838ad99b5718cad46cca693f3 (diff)
parentbe796a3f30d4bec1af7c0e6770a0397dca6ccd4a (diff)
Merge GH #1755 Various BigInt improvements
-rw-r--r--src/lib/math/bigint/big_ops2.cpp70
-rw-r--r--src/lib/math/bigint/big_ops3.cpp17
-rw-r--r--src/lib/math/bigint/bigint.cpp2
-rw-r--r--src/lib/math/bigint/bigint.h14
-rw-r--r--src/lib/math/mp/mp_core.h41
-rw-r--r--src/lib/math/numbertheory/monty.cpp22
-rw-r--r--src/lib/math/numbertheory/nistp_redc.cpp61
-rw-r--r--src/lib/pubkey/ec_group/curve_gfp.cpp9
-rw-r--r--src/lib/pubkey/ec_group/curve_gfp.h7
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.cpp21
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.h3
-rw-r--r--src/tests/data/bn/mod.vec12
-rw-r--r--src/tests/test_bigint.cpp7
13 files changed, 178 insertions, 108 deletions
diff --git a/src/lib/math/bigint/big_ops2.cpp b/src/lib/math/bigint/big_ops2.cpp
index 6ce14f8f1..d35dc082e 100644
--- a/src/lib/math/bigint/big_ops2.cpp
+++ b/src/lib/math/bigint/big_ops2.cpp
@@ -126,19 +126,41 @@ BigInt& BigInt::mod_sub(const BigInt& s, const BigInt& mod, secure_vector<word>&
swap_reg(ws);
}
#else
- // is t < s or not?
- const auto is_lt = bigint_ct_is_lt(data(), mod_sw, s.data(), mod_sw);
+ if(mod_sw == 4)
+ bigint_mod_sub_n<4>(mutable_data(), s.data(), mod.data(), ws.data());
+ else if(mod_sw == 6)
+ bigint_mod_sub_n<6>(mutable_data(), s.data(), mod.data(), ws.data());
+ else
+ bigint_mod_sub(mutable_data(), s.data(), mod.data(), mod_sw, ws.data());
+#endif
- // ws = p - s
- const word borrow = bigint_sub3(ws.data(), mod.data(), mod_sw, s.data(), mod_sw);
+ return (*this);
+ }
- // Compute either (t - s) or (t + (p - s)) depending on mask
- const word carry = bigint_cnd_addsub(is_lt, mutable_data(), ws.data(), s.data(), mod_sw);
+BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws)
+ {
+ BOTAN_ARG_CHECK(this->is_negative() == false, "*this must be positive");
+ BOTAN_ARG_CHECK(y < 16, "y too large");
- BOTAN_DEBUG_ASSERT(borrow == 0 && carry == 0);
- BOTAN_UNUSED(carry, borrow);
-#endif
+ BOTAN_DEBUG_ASSERT(*this < mod);
+
+ switch(y)
+ {
+ case 2:
+ *this <<= 1;
+ break;
+ case 4:
+ *this <<= 2;
+ break;
+ case 8:
+ *this <<= 3;
+ break;
+ default:
+ *this *= static_cast<word>(y);
+ break;
+ }
+ this->reduce_below(mod, ws);
return (*this);
}
@@ -271,18 +293,18 @@ word BigInt::operator%=(word mod)
if(mod == 0)
throw BigInt::DivideByZero();
+ word remainder = 0;
+
if(is_power_of_2(mod))
{
- const word remainder = (word_at(0) & (mod - 1));
- m_data.set_to_zero();
- m_data.set_word_at(0, remainder);
- return remainder;
+ remainder = (word_at(0) & (mod - 1));
}
-
- word remainder = 0;
-
- for(size_t j = sig_words(); j > 0; --j)
- remainder = bigint_modop(remainder, word_at(j-1), mod);
+ else
+ {
+ const size_t sw = sig_words();
+ for(size_t i = sw; i > 0; --i)
+ remainder = bigint_modop(remainder, word_at(i-1), mod);
+ }
if(remainder && sign() == BigInt::Negative)
remainder = mod - remainder;
@@ -290,8 +312,7 @@ word BigInt::operator%=(word mod)
m_data.set_to_zero();
m_data.set_word_at(0, remainder);
set_sign(BigInt::Positive);
-
- return word_at(0);
+ return remainder;
}
/*
@@ -301,9 +322,9 @@ BigInt& BigInt::operator<<=(size_t shift)
{
if(shift)
{
- const size_t shift_words = shift / BOTAN_MP_WORD_BITS,
- shift_bits = shift % BOTAN_MP_WORD_BITS,
- words = sig_words();
+ const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
+ const size_t shift_bits = shift % BOTAN_MP_WORD_BITS;
+ const size_t words = size();
/*
* FIXME - if shift_words == 0 && the top shift_bits of the top word
@@ -329,9 +350,8 @@ BigInt& BigInt::operator>>=(size_t shift)
{
const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
const size_t shift_bits = shift % BOTAN_MP_WORD_BITS;
- const size_t sw = sig_words();
- bigint_shr1(m_data.mutable_data(), sw, shift_words, shift_bits);
+ bigint_shr1(m_data.mutable_data(), m_data.size(), shift_words, shift_bits);
if(is_negative() && is_zero())
set_sign(Positive);
diff --git a/src/lib/math/bigint/big_ops3.cpp b/src/lib/math/bigint/big_ops3.cpp
index a38448050..7a4c8f215 100644
--- a/src/lib/math/bigint/big_ops3.cpp
+++ b/src/lib/math/bigint/big_ops3.cpp
@@ -127,13 +127,20 @@ word operator%(const BigInt& n, word mod)
if(mod == 1)
return 0;
- if(is_power_of_2(mod))
- return (n.word_at(0) & (mod - 1));
-
word remainder = 0;
- for(size_t j = n.sig_words(); j > 0; --j)
- remainder = bigint_modop(remainder, n.word_at(j-1), mod);
+ if(is_power_of_2(mod))
+ {
+ remainder = (n.word_at(0) & (mod - 1));
+ }
+ else
+ {
+ const size_t sw = n.sig_words();
+ for(size_t i = sw; i > 0; --i)
+ {
+ remainder = bigint_modop(remainder, n.word_at(i-1), mod);
+ }
+ }
if(remainder && n.sign() == BigInt::Negative)
return mod - remainder;
diff --git a/src/lib/math/bigint/bigint.cpp b/src/lib/math/bigint/bigint.cpp
index 667035686..d64082476 100644
--- a/src/lib/math/bigint/bigint.cpp
+++ b/src/lib/math/bigint/bigint.cpp
@@ -335,8 +335,6 @@ void BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws)
for(;;)
{
word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
-
- //CT::unpoison(borrow); // fixme
if(borrow)
break;
diff --git a/src/lib/math/bigint/bigint.h b/src/lib/math/bigint/bigint.h
index 58c45dd67..9b385348e 100644
--- a/src/lib/math/bigint/bigint.h
+++ b/src/lib/math/bigint/bigint.h
@@ -328,7 +328,17 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
BigInt& mod_sub(const BigInt& y, const BigInt& mod, secure_vector<word>& ws);
/**
- * Return *this below mod
+ * Set *this to (*this * y) % mod
+ * This function assumes *this is >= 0 && < mod
+ * y should be small, less than 16
+ * @param y the small integer to multiply by
+ * @param mod the positive modulus
+ * @param ws a temp workspace
+ */
+ BigInt& mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws);
+
+ /**
+ * Return *this % mod
*
* Assumes that *this is (if anything) only slightly larger than
* mod and performs repeated subtractions. It should not be used if
@@ -933,7 +943,7 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
if(n > size())
{
if(n <= m_reg.capacity())
- m_reg.resize(m_reg.capacity());
+ m_reg.resize(n);
else
m_reg.resize(n + (8 - (n % 8)));
}
diff --git a/src/lib/math/mp/mp_core.h b/src/lib/math/mp/mp_core.h
index 6e2fba049..2824a3456 100644
--- a/src/lib/math/mp/mp_core.h
+++ b/src/lib/math/mp/mp_core.h
@@ -685,6 +685,47 @@ bigint_sub_abs(word z[],
}
/**
+* Set t to t-s modulo mod
+*
+* @param t first integer
+* @param s second integer
+* @param mod the modulus
+* @param mod_sw size of t, s, and mod
+* @param ws workspace of size mod_sw
+*/
+inline void
+bigint_mod_sub(word t[], const word s[], const word mod[], size_t mod_sw, word ws[])
+ {
+ // is t < s or not?
+ const auto is_lt = bigint_ct_is_lt(t, mod_sw, s, mod_sw);
+
+ // ws = p - s
+ const word borrow = bigint_sub3(ws, mod, mod_sw, s, mod_sw);
+
+ // Compute either (t - s) or (t + (p - s)) depending on mask
+ const word carry = bigint_cnd_addsub(is_lt, t, ws, s, mod_sw);
+
+ BOTAN_DEBUG_ASSERT(borrow == 0 && carry == 0);
+ BOTAN_UNUSED(carry, borrow);
+ }
+
+template<size_t N>
+inline void bigint_mod_sub_n(word t[], const word s[], const word mod[], word ws[])
+ {
+ // is t < s or not?
+ const auto is_lt = bigint_ct_is_lt(t, N, s, N);
+
+ // ws = p - s
+ const word borrow = bigint_sub3(ws, mod, N, s, N);
+
+ // Compute either (t - s) or (t + (p - s)) depending on mask
+ const word carry = bigint_cnd_addsub(is_lt, t, ws, s, N);
+
+ BOTAN_DEBUG_ASSERT(borrow == 0 && carry == 0);
+ BOTAN_UNUSED(carry, borrow);
+ }
+
+/**
* Compute ((n1<<bits) + n0) / d
*/
inline word bigint_divop(word n1, word n0, word d)
diff --git a/src/lib/math/numbertheory/monty.cpp b/src/lib/math/numbertheory/monty.cpp
index 61a10eae5..f3d85e44c 100644
--- a/src/lib/math/numbertheory/monty.cpp
+++ b/src/lib/math/numbertheory/monty.cpp
@@ -312,17 +312,17 @@ BigInt Montgomery_Int::value() const
Montgomery_Int Montgomery_Int::operator+(const Montgomery_Int& other) const
{
- BigInt z = m_v + other.m_v;
secure_vector<word> ws;
- z.reduce_below(m_params->p(), ws);
+ BigInt z = m_v;
+ z.mod_add(other.m_v, m_params->p(), ws);
return Montgomery_Int(m_params, z, false);
}
Montgomery_Int Montgomery_Int::operator-(const Montgomery_Int& other) const
{
- BigInt z = m_v - other.m_v;
- if(z.is_negative())
- z += m_params->p();
+ secure_vector<word> ws;
+ BigInt z = m_v;
+ z.mod_sub(other.m_v, m_params->p(), ws);
return Montgomery_Int(m_params, z, false);
}
@@ -420,29 +420,25 @@ Montgomery_Int Montgomery_Int::additive_inverse() const
Montgomery_Int& Montgomery_Int::mul_by_2(secure_vector<word>& ws)
{
- m_v <<= 1;
- m_v.reduce_below(m_params->p(), ws);
+ m_v.mod_mul(2, m_params->p(), ws);
return (*this);
}
Montgomery_Int& Montgomery_Int::mul_by_3(secure_vector<word>& ws)
{
- m_v *= 3;
- m_v.reduce_below(m_params->p(), ws);
+ m_v.mod_mul(3, m_params->p(), ws);
return (*this);
}
Montgomery_Int& Montgomery_Int::mul_by_4(secure_vector<word>& ws)
{
- m_v <<= 2;
- m_v.reduce_below(m_params->p(), ws);
+ m_v.mod_mul(4, m_params->p(), ws);
return (*this);
}
Montgomery_Int& Montgomery_Int::mul_by_8(secure_vector<word>& ws)
{
- m_v <<= 3;
- m_v.reduce_below(m_params->p(), ws);
+ m_v.mod_mul(8, m_params->p(), ws);
return (*this);
}
diff --git a/src/lib/math/numbertheory/nistp_redc.cpp b/src/lib/math/numbertheory/nistp_redc.cpp
index a74c4de9f..caa071668 100644
--- a/src/lib/math/numbertheory/nistp_redc.cpp
+++ b/src/lib/math/numbertheory/nistp_redc.cpp
@@ -8,6 +8,7 @@
#include <botan/curve_nistp.h>
#include <botan/internal/mp_core.h>
#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
namespace Botan {
@@ -25,6 +26,20 @@ void redc_p521(BigInt& x, secure_vector<word>& ws)
const size_t p_top_bits = 521 % BOTAN_MP_WORD_BITS;
const size_t p_words = p_full_words + 1;
+#if (BOTAN_MP_WORD_BITS == 64)
+ static const word p521_words[p_words] = {
+ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
+ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
+ 0x1FF };
+#else
+ static const word p521_words[p_words] = {
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x1FF };
+#endif
+
if(ws.size() < p_words + 1)
ws.resize(p_words + 1);
@@ -38,39 +53,26 @@ void redc_p521(BigInt& x, secure_vector<word>& ws)
word carry = bigint_add3_nc(x.mutable_data(), x.data(), p_words, ws.data(), p_words);
BOTAN_ASSERT_EQUAL(carry, 0, "Final carry in P-521 reduction");
- // Now find the actual carry in bit 522
- const word bit_522_set = x.word_at(p_full_words) >> p_top_bits;
+ const word top_word = x.word_at(p_full_words);
/*
- * If bit 522 is set then we overflowed and must reduce. Otherwise, if the
- * top bit is set, it is possible we have x == 2**521 - 1 so check for that.
+ * Check if we need to reduce modulo P
+ * There are two possible cases:
+ * - The result overflowed past 521 bits, in which case bit 522 will be set
+ * - The result is exactly 2**521 - 1
*/
- if(bit_522_set)
- {
-#if (BOTAN_MP_WORD_BITS == 64)
- static const word p521_words[9] = {
- 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
- 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
- 0x1FF };
+ const auto bit_522_set = CT::Mask<word>::expand(top_word >> p_top_bits);
- bigint_sub2(x.mutable_data(), p_words, p521_words, 9);
-#else
- x -= prime_p521();
-#endif
- }
- else if(x.word_at(p_full_words) >> (p_top_bits - 1))
- {
- /*
- * Otherwise we must reduce if p is exactly 2^512-1
- */
-
- word possibly_521 = MP_WORD_MAX;
- for(size_t i = 0; i != p_full_words; ++i)
- possibly_521 &= x.word_at(i);
-
- if(possibly_521 == MP_WORD_MAX)
- x.reduce_below(prime_p521(), ws);
- }
+ word and_512 = MP_WORD_MAX;
+ for(size_t i = 0; i != p_full_words; ++i)
+ and_512 &= x.word_at(i);
+ const auto all_512_low_bits_set = CT::Mask<word>::is_equal(and_512, MP_WORD_MAX);
+ const auto has_p521_top_word = CT::Mask<word>::is_equal(top_word, 0x1FF);
+ const auto is_p521 = all_512_low_bits_set & has_p521_top_word;
+
+ const auto needs_reduction = is_p521 | bit_522_set;
+
+ bigint_cnd_sub(needs_reduction.value(), x.mutable_data(), p521_words, p_words);
}
#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32)
@@ -576,5 +578,4 @@ void redc_p384(BigInt& x, secure_vector<word>& ws)
#endif
-
}
diff --git a/src/lib/pubkey/ec_group/curve_gfp.cpp b/src/lib/pubkey/ec_group/curve_gfp.cpp
index bd68a3ed7..f2f5607e1 100644
--- a/src/lib/pubkey/ec_group/curve_gfp.cpp
+++ b/src/lib/pubkey/ec_group/curve_gfp.cpp
@@ -60,8 +60,6 @@ class CurveGFp_Montgomery final : public CurveGFp_Repr
size_t get_ws_size() const override { return 2*m_p_words + 4; }
- void redc_mod_p(BigInt& z, secure_vector<word>& ws) const override;
-
BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
void to_curve_rep(BigInt& x, secure_vector<word>& ws) const override;
@@ -93,11 +91,6 @@ class CurveGFp_Montgomery final : public CurveGFp_Repr
bool m_a_is_minus_3;
};
-void CurveGFp_Montgomery::redc_mod_p(BigInt& z, secure_vector<word>& ws) const
- {
- z.reduce_below(m_p, ws);
- }
-
BigInt CurveGFp_Montgomery::invert_element(const BigInt& x, secure_vector<word>& ws) const
{
// Should we use Montgomery inverse instead?
@@ -207,6 +200,8 @@ class CurveGFp_NIST : public CurveGFp_Repr
void from_curve_rep(BigInt& x, secure_vector<word>& ws) const override
{ redc_mod_p(x, ws); }
+ virtual void redc_mod_p(BigInt& z, secure_vector<word>& ws) const = 0;
+
BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const override;
void curve_mul_words(BigInt& z,
diff --git a/src/lib/pubkey/ec_group/curve_gfp.h b/src/lib/pubkey/ec_group/curve_gfp.h
index d03247244..fe7a0a54d 100644
--- a/src/lib/pubkey/ec_group/curve_gfp.h
+++ b/src/lib/pubkey/ec_group/curve_gfp.h
@@ -49,8 +49,6 @@ class BOTAN_UNSTABLE_API CurveGFp_Repr
*/
virtual const BigInt& get_1_rep() const = 0;
- virtual void redc_mod_p(BigInt& z, secure_vector<word>& ws) const = 0;
-
virtual BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const = 0;
virtual void to_curve_rep(BigInt& x, secure_vector<word>& ws) const = 0;
@@ -171,11 +169,6 @@ class BOTAN_UNSTABLE_API CurveGFp final
// TODO: from_rep taking && ref
- void redc_mod_p(BigInt& z, secure_vector<word>& ws) const
- {
- m_repr->redc_mod_p(z, ws);
- }
-
void mul(BigInt& z, const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
{
m_repr->curve_mul(z, x, y, ws);
diff --git a/src/lib/pubkey/ec_group/point_gfp.cpp b/src/lib/pubkey/ec_group/point_gfp.cpp
index 7bc6c4975..b4b3871cb 100644
--- a/src/lib/pubkey/ec_group/point_gfp.cpp
+++ b/src/lib/pubkey/ec_group/point_gfp.cpp
@@ -2,7 +2,7 @@
* Point arithmetic on elliptic curves over GF(p)
*
* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2011,2012,2014,2015 Jack Lloyd
+* 2008-2011,2012,2014,2015,2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -152,6 +152,7 @@ void PointGFp::add_affine(const word x_words[], size_t x_size,
m_curve.sqr(m_coord_x, T0, ws);
m_coord_x.mod_sub(T1, p, sub_ws);
+
m_coord_x.mod_sub(T3, p, sub_ws);
m_coord_x.mod_sub(T3, p, sub_ws);
@@ -303,15 +304,13 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn)
m_curve.sqr(T0, m_coord_y, ws);
m_curve.mul(T1, m_coord_x, T0, ws);
- T1 <<= 2; // * 4
- m_curve.redc_mod_p(T1, sub_ws);
+ T1.mod_mul(4, p, sub_ws);
if(m_curve.a_is_zero())
{
// if a == 0 then 3*x^2 + a*z^4 is just 3*x^2
m_curve.sqr(T4, m_coord_x, ws); // x^2
- T4 *= 3; // 3*x^2
- m_curve.redc_mod_p(T4, sub_ws);
+ T4.mod_mul(3, p, sub_ws); // 3*x^2
}
else if(m_curve.a_is_minus_3())
{
@@ -330,8 +329,7 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn)
m_curve.mul(T4, T2, T3, ws); // (x-z^2)*(x+z^2)
- T4 *= 3; // 3*(x-z^2)*(x+z^2)
- m_curve.redc_mod_p(T4, sub_ws);
+ T4.mod_mul(3, p, sub_ws); // 3*(x-z^2)*(x+z^2)
}
else
{
@@ -340,8 +338,7 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn)
m_curve.mul(T3, m_curve.get_a_rep(), T4, ws); // a*z^4
m_curve.sqr(T4, m_coord_x, ws); // x^2
- T4 *= 3; // 3*x^2
- T4.reduce_below(p, sub_ws);
+ T4.mod_mul(3, p, sub_ws);
T4.mod_add(T3, p, sub_ws); // 3*x^2 + a*z^4
}
@@ -350,8 +347,7 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn)
T2.mod_sub(T1, p, sub_ws);
m_curve.sqr(T3, T0, ws);
- T3 <<= 3;
- m_curve.redc_mod_p(T3, sub_ws);
+ T3.mod_mul(8, p, sub_ws);
T1.mod_sub(T2, p, sub_ws);
@@ -361,8 +357,7 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn)
m_coord_x = T2;
m_curve.mul(T2, m_coord_y, m_coord_z, ws);
- T2 <<= 1;
- m_curve.redc_mod_p(T2, sub_ws);
+ T2.mod_mul(2, p, sub_ws);
m_coord_y = T0;
m_coord_z = T2;
diff --git a/src/lib/pubkey/ec_group/point_gfp.h b/src/lib/pubkey/ec_group/point_gfp.h
index 222b5f474..aa8a7d7bc 100644
--- a/src/lib/pubkey/ec_group/point_gfp.h
+++ b/src/lib/pubkey/ec_group/point_gfp.h
@@ -180,8 +180,7 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final
* Is this the point at infinity?
* @result true, if this point is at infinity, false otherwise.
*/
- bool is_zero() const
- { return (m_coord_x.is_zero() && m_coord_z.is_zero()); }
+ bool is_zero() const { return m_coord_z.is_zero(); }
/**
* Checks whether the point is to be found on the underlying
diff --git a/src/tests/data/bn/mod.vec b/src/tests/data/bn/mod.vec
index fe6492e64..2d4196dbe 100644
--- a/src/tests/data/bn/mod.vec
+++ b/src/tests/data/bn/mod.vec
@@ -19,6 +19,18 @@ In1 = -0xE
In2 = 0x7
Output = 0x0
+In1 = -15
+In2 = 7
+Output = 6
+
+In1 = -15
+In2 = 8
+Output = 1
+
+In1 = -15
+In2 = 128
+Output = 113
+
In1 = 0x0
In2 = 0x1E8D2D00
Output = 0x0
diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp
index 3870c5c6f..c7b95b89a 100644
--- a/src/tests/test_bigint.cpp
+++ b/src/tests/test_bigint.cpp
@@ -433,12 +433,15 @@ class BigInt_Mod_Test final : public Text_Based_Test
result.test_eq("Barrett", mod_b.reduce(a), c);
// if b fits into a Botan::word test %= operator for words
- if(b.bytes() <= sizeof(Botan::word))
+ if(b.sig_words() == 1)
{
- Botan::word b_word = b.word_at(0);
+ const Botan::word b_word = b.word_at(0);
+
e = a;
e %= b_word;
result.test_eq("a %= b (as word)", e, c);
+
+ result.test_eq("a % b (as word)", a % b_word, c);
}
return result;