aboutsummaryrefslogtreecommitdiffstats
path: root/src/math
diff options
context:
space:
mode:
Diffstat (limited to 'src/math')
-rw-r--r--src/math/gfpmath/curve_gfp.cpp58
-rw-r--r--src/math/gfpmath/curve_gfp.h133
-rw-r--r--src/math/gfpmath/gfp_element.cpp559
-rw-r--r--src/math/gfpmath/gfp_element.h230
-rw-r--r--src/math/gfpmath/gfp_modulus.h131
-rw-r--r--src/math/gfpmath/info.txt19
-rw-r--r--src/math/gfpmath/point_gfp.cpp750
-rw-r--r--src/math/gfpmath/point_gfp.h268
-rw-r--r--src/math/numbertheory/curve_gfp.h96
-rw-r--r--src/math/numbertheory/info.txt3
-rw-r--r--src/math/numbertheory/numthry.cpp100
-rw-r--r--src/math/numbertheory/numthry.h16
-rw-r--r--src/math/numbertheory/point_gfp.cpp423
-rw-r--r--src/math/numbertheory/point_gfp.h201
-rw-r--r--src/math/numbertheory/reducer.cpp19
-rw-r--r--src/math/numbertheory/reducer.h32
16 files changed, 806 insertions, 2232 deletions
diff --git a/src/math/gfpmath/curve_gfp.cpp b/src/math/gfpmath/curve_gfp.cpp
deleted file mode 100644
index e6e69ab0f..000000000
--- a/src/math/gfpmath/curve_gfp.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* Elliptic curves over GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/curve_gfp.h>
-#include <botan/bigint.h>
-#include <assert.h>
-#include <ostream>
-
-namespace Botan {
-
-CurveGFp::CurveGFp(const GFpElement& a, const GFpElement& b,
- const BigInt& p) :
- modulus(p), mA(a), mB(b),
- mres_a(mA), mres_b(mB), mres_one(p, 1)
- {
- if(p != mA.get_p() || p != mB.get_p())
- throw Invalid_Argument("could not construct curve: moduli of arguments differ");
-
- mres_a.turn_on_sp_red_mul();
- mres_a.get_mres();
-
- mres_b.turn_on_sp_red_mul();
- mres_b.get_mres();
-
- mres_one.turn_on_sp_red_mul();
- mres_one.get_mres();
- }
-
-// swaps the states of *this and other, does not throw
-void CurveGFp::swap(CurveGFp& other)
- {
- std::swap(mA, other.mA);
- std::swap(mB, other.mB);
- std::swap(modulus, other.modulus);
- std::swap(mres_a, other.mres_a);
- std::swap(mres_b, other.mres_b);
- std::swap(mres_one, other.mres_one);
- }
-
-bool operator==(const CurveGFp& lhs, const CurveGFp& rhs)
- {
- return (lhs.get_p() == rhs.get_p() &&
- lhs.get_a() == rhs.get_a() &&
- lhs.get_b() == rhs.get_b());
- }
-
-std::ostream& operator<<(std::ostream& output, const CurveGFp& elem)
- {
- return output << "y^2 = x^3 + (" << elem.get_a() << ")x + (" << elem.get_b() << ")";
- }
-
-}
diff --git a/src/math/gfpmath/curve_gfp.h b/src/math/gfpmath/curve_gfp.h
deleted file mode 100644
index d2ca437fb..000000000
--- a/src/math/gfpmath/curve_gfp.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-* Elliptic curves over GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_GFP_CURVE_H__
-#define BOTAN_GFP_CURVE_H__
-
-#include <botan/bigint.h>
-#include <botan/gfp_element.h>
-#include <iosfwd>
-
-namespace Botan {
-
-/**
-* This class represents an elliptic curve over GF(p)
-*/
-class BOTAN_DLL CurveGFp
- {
- public:
-
- /**
- * Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
- * @param a first coefficient
- * @param b second coefficient
- * @param p prime number of the field
- */
- CurveGFp(const GFpElement& a, const GFpElement& b,
- const BigInt& p);
-
- // CurveGFp(const CurveGFp& other) = default;
- // CurveGFp& operator=(const CurveGFp& other) = default;
-
- // getters
-
- /**
- * Get coefficient a
- * @result coefficient a
- */
- const GFpElement& get_a() const { return mA; }
-
- /**
- * Get coefficient b
- * @result coefficient b
- */
- const GFpElement& get_b() const { return mB; }
-
- /**
- * Get the GFpElement coefficient a transformed
- * to its m-residue. This can be used for efficency reasons: the curve
- * stores the transformed version after the first invocation of this
- * function.
- * @result the coefficient a, transformed to its m-residue
- */
- const GFpElement& get_mres_a() const { return mres_a; }
-
- /**
- * Get the GFpElement coefficient b transformed
- * to its m-residue. This can be used for efficency reasons: the curve
- * stores the transformed version after the first invocation of this
- * function.
- * @result the coefficient b, transformed to its m-residue
- */
- const GFpElement& get_mres_b() const { return mres_b; }
-
- /**
- * Get the GFpElement 1 transformed
- * to its m-residue. This can be used for efficency reasons: the curve
- * stores the transformed version after the first invocation of this
- * function.
- * @result the GFpElement 1, transformed to its m-residue
- */
- const GFpElement& get_mres_one() { return mres_one; }
-
- /**
- * Get prime modulus of the field of the curve
- * @result prime modulus of the field of the curve
- */
- const BigInt& get_p() const { return modulus.get_p(); }
-
- /**
- * swaps the states of *this and other, does not throw
- * @param other The curve to swap values with
- */
- void swap(CurveGFp& other);
-
- private:
- GFpModulus modulus;
- GFpElement mA;
- GFpElement mB;
- GFpElement mres_a, mres_b, mres_one;
- };
-
-// relational operators
-bool operator==(const CurveGFp& lhs, const CurveGFp& rhs);
-
-inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
- {
- return !(lhs == rhs);
- }
-
-// io operators
-std::ostream& operator<<(std::ostream& output, const CurveGFp& elem);
-
-// swaps the states of curve1 and curve2, does not throw!
-// cf. Meyers, Item 25
-inline
-void swap(CurveGFp& curve1, CurveGFp& curve2)
- {
- curve1.swap(curve2);
- }
-
-} // namespace Botan
-
-
-namespace std {
-
-// swaps the states of curve1 and curve2, does not throw!
-// cf. Meyers, Item 25
-template<> inline
-void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
- Botan::CurveGFp& curve2)
- {
- curve1.swap(curve2);
- }
-
-} // namespace std
-
-#endif
diff --git a/src/math/gfpmath/gfp_element.cpp b/src/math/gfpmath/gfp_element.cpp
deleted file mode 100644
index 3bb4d0002..000000000
--- a/src/math/gfpmath/gfp_element.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
-* Arithmetic for prime fields GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/gfp_element.h>
-#include <botan/numthry.h>
-#include <botan/internal/def_powm.h>
-#include <botan/internal/mp_asm.h>
-#include <botan/internal/mp_asmi.h>
-#include <ostream>
-#include <assert.h>
-
-namespace Botan {
-
-namespace {
-
-void inner_montg_mult_sos(word result[],
- const word* a_bar, const word* b_bar,
- const word* n, const word* n_dash, u32bit s)
- {
- SecureVector<word> t;
- t.grow_to(2*s+1);
-
- // t = a_bar * b_bar
- for (u32bit i=0; i<s; i++)
- {
- word C = 0;
- word S = 0;
- for (u32bit j=0; j<s; j++)
- {
- // we use:
- // word word_madd3(word a, word b, word c, word d, word* carry)
- // returns a * b + c + d and resets the carry (not using it as input)
-
- S = word_madd3(a_bar[j], b_bar[i], t[i+j], &C);
- t[i+j] = S;
- }
- t[i+s] = C;
- }
-
- // ???
- for (u32bit i=0; i<s; i++)
- {
- // word word_madd2(word a, word b, word c, word* carry)
- // returns a * b + c, resets the carry
-
- word C = 0;
- word zero = 0;
- word m = word_madd2(t[i], n_dash[0], &zero);
-
- for (u32bit j=0; j<s; j++)
- {
- word S = word_madd3(m, n[j], t[i+j], &C);
- t[i+j] = S;
- }
-
- //// mp_mulop.cpp:
- ////word bigint_mul_add_words(word z[], const word x[], u32bit x_size, word y)
- u32bit cnt = 0;
- while (C > 0)
- {
- // we need not worry here about C > 1, because the other operand is zero
-
- word tmp = t[i+s+cnt] + C;
- C = (tmp < t[i+s+cnt]);
- t[i+s+cnt] = tmp;
- cnt++;
- }
- }
-
- // u = t
- SecureVector<word> u;
- u.grow_to(s+1);
- for (u32bit j=0; j<s+1; j++)
- {
- u[j] = t[j+s];
- }
-
- // t = u - n
- word B = 0;
- word D = 0;
- for (u32bit i=0; i<s; i++)
- {
- D = word_sub(u[i], n[i], &B);
- t[i] = D;
- }
- D = word_sub(u[s], 0, &B);
- t[s] = D;
-
- // if t >= 0 (B == 0 -> no borrow), return t
- if(B == 0)
- {
- for (u32bit i=0; i<s; i++)
- {
- result[i] = t[i];
- }
- }
- else // else return u
- {
- for (u32bit i=0; i<s; i++)
- {
- result[i] = u[i];
- }
- }
- }
-
-void montg_mult(BigInt& result, BigInt& a_bar, BigInt& b_bar, const BigInt& m, const BigInt& m_dash, const BigInt)
- {
- if(m.is_zero() || m_dash.is_zero())
- throw Invalid_Argument("montg_mult(): neither modulus nor m_dash may be zero (and one of them was)");
-
- if(a_bar.is_zero() || b_bar.is_zero())
- result = 0;
-
- u32bit s = m.sig_words();
- a_bar.grow_to(s);
- b_bar.grow_to(s);
- result.grow_to(s);
-
- inner_montg_mult_sos(result.get_reg(), a_bar.data(), b_bar.data(),
- m.data(), m_dash.data(), s);
- }
-
-/**
-* Calculates R=b^n (here b=2) with R>m (and R beeing as small as
-* possible) for an odd modulus m. No check for parity is performed!
-*/
-BigInt montgm_calc_r_oddmod(const BigInt& prime)
- {
- u32bit n = prime.sig_words();
- BigInt result(1);
- result <<= n*BOTAN_MP_WORD_BITS;
- return result;
- }
-
-/**
-*calculates m' with r*r^-1 - m*m' = 1
-* where r^-1 is the multiplicative inverse of r to the modulus m
-*/
-BigInt montgm_calc_m_dash(const BigInt& r, const BigInt& m, const BigInt& r_inv)
- {
- BigInt result = ((r * r_inv) - BigInt(1))/m;
- return result;
- }
-
-BigInt montg_trf_to_mres(const BigInt& ord_res, const BigInt& r, const BigInt& m)
- {
- BigInt result(ord_res);
- result *= r;
- result %= m;
- return result;
- }
-
-BigInt montg_trf_to_ordres(const BigInt& m_res, const BigInt& m, const BigInt& r_inv)
- {
- BigInt result(m_res);
- result *= r_inv;
- result %= m;
- return result;
- }
-
-}
-
-GFpElement::GFpElement(const BigInt& p, const BigInt& value, bool use_montgomery)
- : modulus(p), m_value(value %p), m_use_montgm(use_montgomery), m_is_trf(false)
- {
- if(m_use_montgm)
- ensure_montgm_precomp();
- }
-
-void GFpElement::turn_on_sp_red_mul()
- {
- ensure_montgm_precomp();
- m_use_montgm = true;
- }
-
-void GFpElement::turn_off_sp_red_mul()
- {
- if(m_is_trf)
- {
- trf_to_ordres();
- // will happen soon anyway, so we can do it here already
- // (this is not lazy but way more secure concerning our internal logic here)
- }
- m_use_montgm = false;
- }
-
-void GFpElement::ensure_montgm_precomp()
- {
- if((!modulus.get_r().is_zero()) && (!modulus.get_r_inv().is_zero()) && (!modulus.get_p_dash().is_zero()))
- {
- // values are already set, nothing more to do
- }
- else
- {
- BigInt tmp_r(montgm_calc_r_oddmod(modulus.get_p()));
-
- BigInt tmp_r_inv(inverse_mod(tmp_r, modulus.get_p()));
-
- BigInt tmp_p_dash(montgm_calc_m_dash(tmp_r, modulus.get_p(), tmp_r_inv));
-
- modulus.reset_values(tmp_p_dash, tmp_r, tmp_r_inv);
- }
-
- }
-
-void GFpElement::trf_to_mres() const
- {
- if(!m_use_montgm)
- {
- throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
- }
- assert(m_is_trf == false);
- assert(!modulus.get_r_inv().is_zero());
- assert(!modulus.get_p_dash().is_zero());
- m_value = montg_trf_to_mres(m_value, modulus.get_r(), modulus.get_p());
- m_is_trf = true;
- }
-
-void GFpElement::trf_to_ordres() const
- {
- assert(m_is_trf == true);
- m_value = montg_trf_to_ordres(m_value, modulus.get_p(), modulus.get_r_inv());
- m_is_trf = false;
- }
-
-bool GFpElement::align_operands_res(const GFpElement& lhs, const GFpElement& rhs) //static
- {
- assert(lhs.modulus.get_p() == rhs.modulus.get_p());
- if(lhs.m_use_montgm && rhs.m_use_montgm)
- {
- assert(rhs.modulus.get_p_dash() == lhs.modulus.get_p_dash());
- assert(rhs.modulus.get_r() == lhs.modulus.get_r());
- assert(rhs.modulus.get_r_inv() == lhs.modulus.get_r_inv());
- if(!lhs.m_is_trf && !rhs.m_is_trf)
- {
- return false;
- }
- else if(lhs.m_is_trf && rhs.m_is_trf)
- {
- return true;
- }
- else // one is transf., the other not
- {
- if(!lhs.m_is_trf)
- {
- lhs.trf_to_mres();
- assert(rhs.m_is_trf==true);
- return true;
- }
- assert(rhs.m_is_trf==false);
- assert(lhs.m_is_trf==true);
- rhs.trf_to_mres(); // the only possibility left...
- return true;
- }
- }
- else // at least one of them does not use mm
- // (so it is impossible that both use it)
- {
- if(lhs.m_is_trf)
- {
- lhs.trf_to_ordres();
- assert(rhs.m_is_trf == false);
- return false;
- }
- if(rhs.m_is_trf)
- {
- rhs.trf_to_ordres();
- assert(lhs.m_is_trf == false);
- return false;
- }
- return false;
- }
- assert(false);
- }
-
-bool GFpElement::is_trf_to_mres() const
- {
- return m_is_trf;
- }
-
-const BigInt& GFpElement::get_p() const
- {
- return (modulus.get_p());
- }
-
-const BigInt& GFpElement::get_value() const
- {
- if(m_is_trf)
- {
- assert(m_use_montgm);
- trf_to_ordres();
- }
- return m_value;
- }
-
-const BigInt& GFpElement::get_mres() const
- {
- if(!m_use_montgm)
- {
- // does the following exception really make sense?
- // wouldn't it be better to simply turn on montg.mult. when
- // this explicit request is made?
- throw Illegal_Transformation("GFpElement is not allowed to be transformed to m-residue");
- }
- if(!m_is_trf)
- {
- trf_to_mres();
- }
-
- return m_value;
- }
-
-GFpElement& GFpElement::operator+=(const GFpElement& rhs)
- {
- GFpElement::align_operands_res(*this, rhs);
-
- BigInt workspace = m_value;
- workspace += rhs.m_value;
- if(workspace >= modulus.get_p())
- workspace -= modulus.get_p();
-
- m_value = workspace;
- assert(m_value < modulus.get_p());
- assert(m_value >= 0);
-
- return *this;
- }
-
-GFpElement& GFpElement::operator-=(const GFpElement& rhs)
- {
- GFpElement::align_operands_res(*this, rhs);
-
- BigInt workspace = m_value;
-
- workspace -= rhs.m_value;
-
- if(workspace.is_negative())
- workspace += modulus.get_p();
-
- m_value = workspace;
- assert(m_value < modulus.get_p());
- assert(m_value >= 0);
- return *this;
- }
-
-GFpElement& GFpElement::operator*= (u32bit rhs)
- {
- BigInt workspace = m_value;
- workspace *= rhs;
- workspace %= modulus.get_p();
- m_value = workspace;
- return *this;
- }
-
-GFpElement& GFpElement::operator*=(const GFpElement& rhs)
- {
- assert(rhs.modulus.get_p() == modulus.get_p());
- // here, we do not use align_operands_res() for one simple reason:
- // we want to enforce the transformation to an m-residue, otherwise it would
- // never happen
- if(m_use_montgm && rhs.m_use_montgm)
- {
- assert(rhs.modulus.get_p() == modulus.get_p()); // is montgm. mult is on, then precomps must be there
- assert(rhs.modulus.get_p_dash() == modulus.get_p_dash());
- assert(rhs.modulus.get_r() == modulus.get_r());
- if(!m_is_trf)
- {
- trf_to_mres();
- }
- if(!rhs.m_is_trf)
- {
- rhs.trf_to_mres();
- }
- BigInt workspace = m_value;
- montg_mult(m_value, workspace, rhs.m_value, modulus.get_p(), modulus.get_p_dash(), modulus.get_r());
- }
- else // ordinary multiplication
- {
- if(m_is_trf)
- {
- assert(m_use_montgm);
- trf_to_ordres();
- }
- if(rhs.m_is_trf)
- {
- assert(rhs.m_use_montgm);
- rhs.trf_to_ordres();
- }
-
- BigInt workspace = m_value;
- workspace *= rhs.m_value;
- workspace %= modulus.get_p();
- m_value = workspace;
- }
- return *this;
- }
-
-GFpElement& GFpElement::operator/=(const GFpElement& rhs)
- {
- bool use_mres = GFpElement::align_operands_res(*this, rhs);
- assert((this->m_is_trf && rhs.m_is_trf) || !(this->m_is_trf && rhs.m_is_trf));
-
- if(use_mres)
- {
- assert(m_use_montgm && rhs.m_use_montgm);
- GFpElement rhs_ordres(rhs);
- rhs_ordres.trf_to_ordres();
- rhs_ordres.inverse_in_place();
- BigInt workspace = m_value;
- workspace *= rhs_ordres.get_value();
- workspace %= modulus.get_p();
- m_value = workspace;
- }
- else
- {
- GFpElement inv_rhs(rhs);
- inv_rhs.inverse_in_place();
- *this *= inv_rhs;
- }
- return *this;
- }
-
-bool GFpElement::is_zero()
- {
- return (m_value.is_zero());
- // this is correct because x_bar = x * r = x = 0 for x = 0
- }
-
-GFpElement& GFpElement::inverse_in_place()
- {
- m_value = inverse_mod(m_value, modulus.get_p());
-
- if(m_is_trf)
- {
- assert(m_use_montgm);
-
- m_value *= modulus.get_r();
- m_value *= modulus.get_r();
- m_value %= modulus.get_p();
- }
- assert(m_value <= modulus.get_p());
- return *this;
- }
-
-GFpElement& GFpElement::negate()
- {
- m_value = modulus.get_p() - m_value;
- assert(m_value <= modulus.get_p());
- return *this;
- }
-
-void GFpElement::swap(GFpElement& other)
- {
- std::swap(m_value, other.m_value);
- std::swap(modulus, other.modulus);
- std::swap<bool>(m_use_montgm,other.m_use_montgm);
- std::swap<bool>(m_is_trf,other.m_is_trf);
- }
-
-std::ostream& operator<<(std::ostream& output, const GFpElement& elem)
- {
- return output << '(' << elem.get_value() << "," << elem.get_p() << ')';
- }
-
-bool operator==(const GFpElement& lhs, const GFpElement& rhs)
- {
- if(lhs.get_p() != rhs.get_p())
- return false;
-
- // so the modulus is equal, now check the values
- bool use_mres = GFpElement::align_operands_res(lhs, rhs);
-
- if(use_mres)
- {
- return (lhs.get_mres() == rhs.get_mres());
- }
- else
- {
- return(lhs.get_value() == rhs.get_value());
- }
- }
-
-GFpElement operator+(const GFpElement& lhs, const GFpElement& rhs)
- {
- // consider the case that lhs and rhs both use montgm:
- // then += returns an element which uses montgm.
- // thus the return value of op+ here will be an element
- // using montgm in this case
- // NOTE: the rhs might be transformed when using op+, the lhs never
- GFpElement result(lhs);
- result += rhs;
- return result;
- }
-
-GFpElement operator-(const GFpElement& lhs, const GFpElement& rhs)
- {
- GFpElement result(lhs);
- result -= rhs;
- return result;
- // NOTE: the rhs might be transformed when using op-, the lhs never
- }
-
-GFpElement operator-(const GFpElement& lhs)
- {
- return(GFpElement(lhs)).negate();
- }
-
-GFpElement operator*(const GFpElement& lhs, const GFpElement& rhs)
- {
- // consider the case that lhs and rhs both use montgm:
- // then *= returns an element which uses montgm.
- // thus the return value of op* here will be an element
- // using montgm in this case
- GFpElement result(lhs);
- result *= rhs;
- return result;
- }
-
-GFpElement operator*(const GFpElement& lhs, u32bit rhs)
- {
- GFpElement result(lhs);
- result *= rhs;
- return result;
- }
-
-GFpElement operator*(u32bit lhs, const GFpElement& rhs)
- {
- return rhs*lhs;
- }
-
-GFpElement operator/(const GFpElement& lhs, const GFpElement& rhs)
- {
- GFpElement result (lhs);
- result /= rhs;
- return result;
- }
-
-SecureVector<byte> FE2OSP(const GFpElement& elem)
- {
- return BigInt::encode_1363(elem.get_value(), elem.get_p().bytes());
- }
-
-GFpElement OS2FEP(MemoryRegion<byte> const& os, BigInt p)
- {
- return GFpElement(p, BigInt::decode(os.begin(), os.size()));
- }
-
-GFpElement inverse(const GFpElement& elem)
- {
- return GFpElement(elem).inverse_in_place();
- }
-
-}
-
diff --git a/src/math/gfpmath/gfp_element.h b/src/math/gfpmath/gfp_element.h
deleted file mode 100644
index 538d41a47..000000000
--- a/src/math/gfpmath/gfp_element.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-* Arithmetic for prime fields GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2009-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_GFP_ELEMENT_H__
-#define BOTAN_GFP_ELEMENT_H__
-
-#include <botan/bigint.h>
-#include <botan/gfp_modulus.h>
-#include <iosfwd>
-
-namespace Botan {
-
-struct BOTAN_DLL Illegal_Transformation : public Exception
- {
- Illegal_Transformation(const std::string& err =
- "Requested transformation is not possible") :
- Exception(err) {}
- };
-
-/**
- * This class represents one element in GF(p). Enables the convenient,
- * transparent use of the montgomery multiplication.
- */
-class BOTAN_DLL GFpElement
- {
- public:
-
- /** construct an element of GF(p) with the given value.
- * use_montg defaults to false and determines wether Montgomery
- * multiplications will be use when applying operators *, *=
- * @param p the prime number of the field
- * @param value the element value
- * @param use_montgm whether this object will use Montgomery multiplication
- */
- GFpElement(const BigInt& p, const BigInt& value, bool use_montgm = true);
-
- // GFpElement(const GFpElement& other) = default;
-
- // const GFpElement& operator=(const GFpElement& other) = default;
-
- /**
- * Switch Montgomery multiplcation optimizations ON
- */
- void turn_on_sp_red_mul();
-
- /**
- * Switch Montgomery multiplcation optimizations OFF
- */
- void turn_off_sp_red_mul();
-
- /**
- * += Operator
- * @param rhs the GFpElement to add to the local value
- * @result *this
- */
- GFpElement& operator+=(const GFpElement& rhs);
-
- /**
- * -= Operator
- * @param rhs the GFpElement to subtract from the local value
- * @result *this
- */
- GFpElement& operator-=(const GFpElement& rhs);
-
- /**
- * *= Operator
- * @param rhs the GFpElement to multiply with the local value
- * @result *this
- */
- GFpElement& operator*=(const GFpElement& rhs);
- /**
- * /= Operator
- * @param rhs the GFpElement to divide the local value by
- * @result *this
- */
- GFpElement& operator/=(const GFpElement& rhs);
-
- /**
- * *= Operator
- * @param rhs the value to multiply with the local value
- * @result *this
- */
- GFpElement& operator*=(u32bit rhs);
-
- /**
- * Negate internal value(*this *= -1 )
- * @return *this
- */
- GFpElement& negate();
-
- /**
- * Assigns the inverse of *this to *this, i.e.
- * *this = (*this)^(-1)
- * @result *this
- */
- GFpElement& inverse_in_place();
-
- /**
- * checks whether the value is zero (without provoking
- * a backtransformation to the ordinary-residue)
- * @result true, if the value is zero, false otherwise.
- */
- bool is_zero();
-
- /**
- * return prime number of GF(p)
- * @result a prime number
- */
- const BigInt& get_p() const;
-
- /**
- * Return the represented value in GF(p)
- * @result The value in GF(p)
- */
- const BigInt& get_value() const;
-
- /**
- * Tells whether this GFpElement is currently transformed to an m-residue,
- * i.e. in the form x_bar = x * r mod m.
- * @result true if it is currently transformed to its m-residue.
- */
- bool is_trf_to_mres() const;
-
- /**
- * Transforms this to x_bar = x * r mod m
- * @result return the value x_bar.
- */
- const BigInt& get_mres() const;
-
- /**
- * Check, if montgomery multiplication is used.
- * @result true, if montgomery multiplication is used, false otherwise
- */
- bool is_use_montgm() const
- {
- return m_use_montgm;
- }
-
- /**
- * Transforms the arguments in such way that either both
- * are in m-residue representation (returns true) or both are
- * in ordinary residue representation (returns false).
- * m-residue is prefered in case of ambiguity.
- * does not toggle m_use_montgm of the arguments.
- * Don't be confused about the constness of the arguments:
- * the transformation between normal residue and m-residue is
- * considered as leaving the object const.
- * @param lhs the first operand to be aligned
- * @param rhs the second operand to be aligned
- * @result true if both are transformed to their m-residue,
- * false it both are transformed to their normal residue.
- */
- static bool align_operands_res(const GFpElement& lhs, const GFpElement& rhs);
-
- /**
- * swaps the states of *this and other, does not throw!
- * @param other The value to swap with
- */
- void swap(GFpElement& other);
- private:
- void ensure_montgm_precomp();
- void trf_to_mres() const;
- void trf_to_ordres() const;
-
- GFpModulus modulus;
- mutable BigInt m_value; // ordinary residue or m-residue respectively
-
- // data members for montgomery multiplication
- bool m_use_montgm;
- mutable bool m_is_trf; // if m_value is montgomery
- };
-
-// relational operators
-bool BOTAN_DLL operator==(const GFpElement& lhs, const GFpElement& rhs);
-inline bool operator!=(const GFpElement& lhs, const GFpElement& rhs )
- {
- return !operator==(lhs, rhs);
- }
-
-// arithmetic operators
-GFpElement BOTAN_DLL operator+(const GFpElement& lhs, const GFpElement& rhs);
-GFpElement BOTAN_DLL operator-(const GFpElement& lhs, const GFpElement& rhs);
-GFpElement BOTAN_DLL operator-(const GFpElement& lhs);
-
-GFpElement BOTAN_DLL operator*(const GFpElement& lhs, const GFpElement& rhs);
-GFpElement BOTAN_DLL operator/(const GFpElement& lhs, const GFpElement& rhs);
-GFpElement BOTAN_DLL operator*(const GFpElement& lhs, u32bit rhs);
-GFpElement BOTAN_DLL operator*(u32bit rhs, const GFpElement& lhs);
-
-
-/**
-* write a GFpElement to an output stream.
-* @param output the output stream to write to
-* @param elem the object to write
-* @result the output stream
-*/
-BOTAN_DLL std::ostream& operator<<(std::ostream& output, const GFpElement& elem);
-
-// return (*this)^(-1)
-GFpElement BOTAN_DLL inverse(const GFpElement& elem);
-
-// encoding and decoding
-SecureVector<byte> BOTAN_DLL FE2OSP(const GFpElement& elem);
-GFpElement BOTAN_DLL OS2FEP(MemoryRegion<byte> const& os, BigInt p);
-
-inline void swap(GFpElement& x, GFpElement& y)
- {
- x.swap(y);
- }
-
-}
-
-namespace std {
-
-template<> inline
-void swap<Botan::GFpElement>(Botan::GFpElement& x,
- Botan::GFpElement& y)
- {
- x.swap(y);
- }
-
-}
-
-#endif
diff --git a/src/math/gfpmath/gfp_modulus.h b/src/math/gfpmath/gfp_modulus.h
deleted file mode 100644
index fcdd13ee1..000000000
--- a/src/math/gfpmath/gfp_modulus.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-* Modulus and related data for a specific implementation of GF(p)
-*
-* (C) 2008 Martin Doering, Christoph Ludwig, Falko Strenzke
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_GFP_MODULUS_H__
-#define BOTAN_GFP_MODULUS_H__
-
-#include <botan/bigint.h>
-
-namespace Botan {
-
-class GFpElement;
-
-/**
-* This class represents a GFpElement modulus including the modulus
-* related values necessary for the montgomery multiplication.
-*/
-class BOTAN_DLL GFpModulus
- {
- public:
-
- /**
- * Construct a GF(P)-Modulus from a BigInt
- */
- GFpModulus(const BigInt& p)
- : m_p(p),
- m_p_dash(),
- m_r(),
- m_r_inv()
- {}
-
- // GFpModulus(const GFpModulus& other) = default;
- // GFpModulus& operator=(const GFpModulus& other) = default;
-
- /**
- * Tells whether the precomputations necessary for the use of the
- * montgomery multiplication have yet been established.
- * @result true if the precomputated value are already available.
- */
- bool has_precomputations() const
- {
- return(!m_p_dash.is_zero() && !m_r.is_zero() && !m_r_inv.is_zero());
- }
-
- /**
- * Swaps this with another GFpModulus, does not throw.
- * @param other the GFpModulus to swap *this with.
- */
- void swap(GFpModulus& other)
- {
- std::swap(m_p, other.m_p);
- std::swap(m_p_dash, other.m_p_dash);
- std::swap(m_r, other.m_r);
- std::swap(m_r_inv, other.m_r_inv);
- }
-
- /**
- * Tells whether the modulus of *this is equal to the argument.
- * @param mod the modulus to compare this with
- * @result true if the modulus of *this and the argument are equal.
- */
- bool p_equal_to(const BigInt& mod) const
- {
- return (m_p == mod);
- }
-
- /**
- * Return the modulus of this GFpModulus.
- * @result the modulus of *this.
- */
- const BigInt& get_p() const
- {
- return m_p;
- }
-
- /**
- * returns the montgomery multiplication related value r.
- * Warning: will be zero if precomputations have not yet been
- * performed!
- * @result r
- */
- const BigInt& get_r() const
- {
- return m_r;
- }
-
- /**
- * returns the montgomery multiplication related value r^{-1}.
- * Warning: will be zero if precomputations have not yet been
- * performed!
- * @result r^{-1}
- */
- const BigInt& get_r_inv() const
- {
- return m_r_inv;
- }
-
- /**
- * returns the montgomery multiplication related value p'.
- * Warning: will be zero if precomputations have not yet been
- * performed!
- * @result p'
- */
- const BigInt& get_p_dash() const
- {
- return m_p_dash;
- }
-
- void reset_values(const BigInt& new_p_dash,
- const BigInt& new_r,
- const BigInt& new_r_inv)
- {
- m_p_dash = new_p_dash;
- m_r = new_r;
- m_r_inv = new_r_inv;
- }
-
- private:
- BigInt m_p; // the modulus itself
- BigInt m_p_dash;
- BigInt m_r;
- BigInt m_r_inv;
- };
-
-}
-
-#endif
diff --git a/src/math/gfpmath/info.txt b/src/math/gfpmath/info.txt
deleted file mode 100644
index b7b430805..000000000
--- a/src/math/gfpmath/info.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-define BIGINT_GFP
-
-<header:public>
-curve_gfp.h
-gfp_element.h
-gfp_modulus.h
-point_gfp.h
-</header:public>
-
-<source>
-curve_gfp.cpp
-gfp_element.cpp
-point_gfp.cpp
-</source>
-
-<requires>
-bigint
-numbertheory
-</requires>
diff --git a/src/math/gfpmath/point_gfp.cpp b/src/math/gfpmath/point_gfp.cpp
deleted file mode 100644
index 4b2de7913..000000000
--- a/src/math/gfpmath/point_gfp.cpp
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
-* Arithmetic for point groups of elliptic curves over GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/point_gfp.h>
-#include <botan/numthry.h>
-
-namespace Botan {
-
-// construct the point at infinity or a random point
-PointGFp::PointGFp(const CurveGFp& curve) :
- mC(curve),
- mX(curve.get_p(), 0),
- mY(curve.get_p(), 1),
- mZ(curve.get_p(), 0)
- {
- }
-
-// construct a point given its jacobian projective coordinates
-PointGFp::PointGFp(const CurveGFp& curve, const GFpElement& x,
- const GFpElement& y, const GFpElement& z) :
- mC(curve),
- mX(x),
- mY(y),
- mZ(z)
- {
- }
-
-PointGFp::PointGFp(const CurveGFp& curve,
- const GFpElement& x,
- const GFpElement& y) :
- mC(curve),
- mX(x),
- mY(y),
- mZ(curve.get_p(),1)
- {
- }
-
-// arithmetic operators
-PointGFp& PointGFp::operator+=(const PointGFp& rhs)
- {
- if(is_zero())
- {
- *this = rhs;
- return *this;
- }
- if(rhs.is_zero())
- {
- return *this;
- }
-
- GFpElement U1 = mX;
- GFpElement S1 = mY;
-
- if(rhs.mZ != mC.get_mres_one())
- {
- GFpElement rhs_z2 = rhs.mZ * rhs.mZ;
-
- U1 *= rhs_z2;
- S1 *= rhs_z2 * rhs.mZ;
- }
-
- GFpElement U2 = rhs.mX;
- GFpElement S2 = rhs.mY;
-
- if(mZ != mC.get_mres_one())
- {
- GFpElement lhs_z2 = mZ * mZ;
-
- U2 *= lhs_z2;
- S2 *= lhs_z2 * mZ;
- }
-
- GFpElement H(U2 - U1);
- GFpElement r(S2 - S1);
-
- if(H.is_zero())
- {
- if(r.is_zero())
- {
- mult2_in_place();
- return *this;
- }
-
- *this = PointGFp(mC); // setting myself to zero
- return *this;
- }
-
- U2 = H * H;
-
- S2 = U2 * H;
-
- U2 *= U1;
-
- GFpElement x(r*r - S2 - (U2+U2));
-
- GFpElement z(S1 * S2);
-
- GFpElement y(r * (U2-x) - z);
-
- if(mZ == mC.get_mres_one())
- {
- if(rhs.mZ != mC.get_mres_one())
- z = rhs.mZ * H;
- else
- z = H;
- }
- else if(rhs.mZ != mC.get_mres_one())
- {
- U1 = mZ * rhs.mZ;
- z = U1 * H;
- }
- else
- z = mZ * H;
-
- mX = x;
- mY = y;
- mZ = z;
-
- return *this;
-
- }
-PointGFp& PointGFp::operator-=(const PointGFp& rhs)
- {
- PointGFp minus_rhs = PointGFp(rhs).negate();
-
- if(is_zero())
- {
- *this = minus_rhs;
- }
- else
- {
- *this += minus_rhs;
- }
- return *this;
- }
-
-PointGFp& PointGFp::mult_this_secure(const BigInt& scalar,
- const BigInt& /*point_order*/,
- const BigInt& /*max_secr*/)
- {
- // NOTE: FS: so far this is code duplication of op*=.
- // we have to see how we deal with this.
- // fact is that we will probably modify this function
- // while evaluating the countermeasures
- // whereas we probably will not start modifying the
- // function operator*=.
- // however, in the end both should be merged.
-
- // use montgomery mult. in this operation
- this->turn_on_sp_red_mul();
-
- PointGFp H(mC);
-
- PointGFp P(*this);
- BigInt m(scalar);
-
- if(m < BigInt(0))
- {
- m = -m;
- P.negate();
- }
- if(P.is_zero() || (m == BigInt(0)))
- {
- *this = H;
- return *this;
- }
- if(m == BigInt(1))
- return *this;
-
- int mul_bits = m.bits();
-
- for(int i = mul_bits - 1; i >= 0; i--)
- {
- H.mult2_in_place();
-
- if(m.get_bit(i))
- H += P;
- }
-
- if(!H.is_zero()) // cannot convert if H == O
- *this = H.get_z_to_one();
- else
- *this = H;
-
- mX.turn_off_sp_red_mul();
- mY.turn_off_sp_red_mul();
- mZ.turn_off_sp_red_mul();
- return *this;
- }
-
-PointGFp& PointGFp::operator*=(const BigInt& scalar)
- {
- // use montgomery mult. in this operation
-
- this->turn_on_sp_red_mul();
-
- PointGFp H(this->mC); // create as zero
- H.turn_on_sp_red_mul();
- PointGFp P(*this);
- P.turn_on_sp_red_mul();
- BigInt m(scalar);
-
- if(m < BigInt(0))
- {
- m = -m;
- P.negate();
- }
-
- if(P.is_zero() || (m == BigInt(0)))
- {
- *this = H;
- return *this;
- }
-
- if(m == BigInt(1)) //*this == P already
- return *this;
-
- const int l = m.bits() - 1;
- for(int i = l; i >= 0; --i)
- {
- H.mult2_in_place();
- if(m.get_bit(i))
- H += P;
- }
-
- if(!H.is_zero()) // cannot convert if H == O
- *this = H.get_z_to_one();
- else
- *this = H;
-
- return *this;
- }
-
-PointGFp& PointGFp::negate()
- {
- if(!is_zero())
- mY.negate();
-
- return *this;
- }
-
-// *this *= 2
-PointGFp& PointGFp::mult2_in_place()
- {
- if(is_zero())
- return *this;
- else if(mY.is_zero())
- {
- *this = PointGFp(mC); // setting myself to zero
- return *this;
- }
-
- GFpElement Y_squared = mY*mY;
-
- GFpElement S = mX * Y_squared;
-
- GFpElement x = S + S;
-
- S = x + x;
-
- GFpElement a_z4 = mC.get_mres_a();
- if(mZ != mC.get_mres_one())
- {
- GFpElement z2 = mZ * mZ;
- a_z4 *= z2;
- a_z4 *= z2;
- }
-
- GFpElement y(mX * mX);
-
- GFpElement M(y + y + y + a_z4);
-
- x = M * M - (S+S);
-
- y = Y_squared * Y_squared;
-
- GFpElement U(y + y);
-
- GFpElement z = U + U;
-
- U = z + z;
-
- y = M * (S - x) - U;
-
- if(mZ != mC.get_mres_one())
- z = mY * mZ;
- else
- z = mY;
-
- z = z + z;
-
- mX = x;
- mY = y;
- mZ = z;
-
- return *this;
- }
-
-void PointGFp::turn_on_sp_red_mul() const
- {
- mX.turn_on_sp_red_mul();
- mY.turn_on_sp_red_mul();
- mZ.turn_on_sp_red_mul();
-
- // also pretransform, otherwise
- // we might have bad results with respect to
- // performance because
- // additions/subtractions in mult2_in_place()
- // and op+= spread untransformed GFpElements
- mX.get_mres();
- mY.get_mres();
- mZ.get_mres();
- }
-
-/**
-* returns a point equivalent to *this but were
-* Z has value one, i.e. x and y correspond to
-* their values in affine coordinates
-*/
-PointGFp PointGFp::get_z_to_one() const
- {
- return PointGFp(*this).set_z_to_one();
- }
-
-/**
-* changes the representation of *this so that
-* Z has value one, i.e. x and y correspond to
-* their values in affine coordinates.
-* returns *this.
-*/
-const PointGFp& PointGFp::set_z_to_one() const
- {
- if(!(mZ.get_value() == BigInt(1)) && !(mZ.get_value() == BigInt(0)))
- {
- GFpElement z = inverse(mZ);
- GFpElement z2 = z * z;
- z *= z2;
- GFpElement x = mX * z2;
- GFpElement y = mY * z;
- mZ = GFpElement(mC.get_p(), BigInt(1));
- mX = x;
- mY = y;
- }
- else
- {
- if(mZ.get_value() == BigInt(0))
- {
- throw Illegal_Transformation("cannot convert Z to one");
- }
- }
- return *this; // mZ = 1 already
- }
-
-GFpElement PointGFp::get_affine_x() const
- {
- if(is_zero())
- throw Illegal_Transformation("cannot convert to affine");
-
- GFpElement z2 = mZ * mZ;
- return mX * z2.inverse_in_place();
- }
-
-GFpElement PointGFp::get_affine_y() const
- {
- if(is_zero())
- throw Illegal_Transformation("cannot convert to affine");
-
- GFpElement z3 = mZ * mZ * mZ;
- return mY * z3.inverse_in_place();
- }
-
-GFpElement PointGFp::get_jac_proj_x() const
- {
- return GFpElement(mX);
- }
-
-GFpElement PointGFp::get_jac_proj_y() const
- {
- return GFpElement(mY);
- }
-
-GFpElement PointGFp::get_jac_proj_z() const
- {
- return GFpElement(mZ);
- }
-
-// Is this the point at infinity?
-bool PointGFp::is_zero() const
- {
- return(mX.is_zero() && mZ.is_zero());
- //NOTE: the calls to GFpElement::is_zero() instead of getting the value and
- // and comparing it are import because they do not provoke backtransformations
- // to the ordinary residue.
- }
-
-// Is the point still on the curve??
-// (If everything is correct, the point is always on its curve; then the
-// function will return silently. If Oskar managed to corrupt this object's state,
-// then it will throw an exception.)
-
-void PointGFp::check_invariants() const
- {
- if(is_zero())
- {
- return;
- }
- const GFpElement y2 = mY * mY;
- const GFpElement x3 = mX * mX * mX;
-
- if(mZ.get_value() == BigInt(1))
- {
- GFpElement ax = mC.get_a() * mX;
- if(y2 != (x3 + ax + mC.get_b()))
- {
- throw Illegal_Point();
- }
-
- }
-
- GFpElement Zpow2 = mZ * mZ;
- GFpElement Zpow3 = Zpow2 * mZ;
- GFpElement AZpow4 = Zpow3 * mZ * mC.get_a();
- const GFpElement aXZ4 = AZpow4 * mX;
- const GFpElement bZ6 = mC.get_b() * Zpow3 * Zpow3;
-
- if(y2 != (x3 + aXZ4 + bZ6))
- throw Illegal_Point();
- }
-
-// swaps the states of *this and other, does not throw!
-void PointGFp::swap(PointGFp& other)
- {
- mC.swap(other.mC);
- mX.swap(other.mX);
- mY.swap(other.mY);
- mZ.swap(other.mZ);
- }
-
-PointGFp mult2(const PointGFp& point)
- {
- return (PointGFp(point)).mult2_in_place();
- }
-
-bool operator==(const PointGFp& lhs, PointGFp const& rhs)
- {
- if(lhs.is_zero() && rhs.is_zero())
- {
- return true;
- }
- if((lhs.is_zero() && !rhs.is_zero()) || (!lhs.is_zero() && rhs.is_zero()))
- {
- return false;
- }
- // neither operand is zero, so we can call get_z_to_one()
- //assert(!lhs.is_zero());
- //assert(!rhs.is_zero());
- PointGFp aff_lhs = lhs.get_z_to_one();
- PointGFp aff_rhs = rhs.get_z_to_one();
- return (aff_lhs.get_curve() == aff_rhs.get_curve() &&
- aff_lhs.get_jac_proj_x() == aff_rhs.get_jac_proj_x() &&
- aff_lhs.get_jac_proj_y() == aff_rhs.get_jac_proj_y());
- }
-
-// arithmetic operators
-PointGFp operator+(const PointGFp& lhs, PointGFp const& rhs)
- {
- PointGFp tmp(lhs);
- return tmp += rhs;
- }
-
-PointGFp operator-(const PointGFp& lhs, PointGFp const& rhs)
- {
- PointGFp tmp(lhs);
- return tmp -= rhs;
- }
-
-PointGFp operator-(const PointGFp& lhs)
- {
- return PointGFp(lhs).negate();
- }
-
-PointGFp operator*(const BigInt& scalar, const PointGFp& point)
- {
- PointGFp result(point);
- return result *= scalar;
- }
-
-PointGFp operator*(const PointGFp& point, const BigInt& scalar)
- {
- PointGFp result(point);
- return result *= scalar;
- }
-
-PointGFp mult_point_secure(const PointGFp& point, const BigInt& scalar,
- const BigInt& point_order, const BigInt& max_secret)
- {
- PointGFp result(point);
- result.mult_this_secure(scalar, point_order, max_secret);
- return result;
- }
-
-// encoding and decoding
-SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
- {
- SecureVector<byte> result;
- if(format == PointGFp::UNCOMPRESSED)
- {
- result = encode_uncompressed(point);
- }
- else if(format == PointGFp::COMPRESSED)
- {
- result = encode_compressed(point);
-
- }
- else if(format == PointGFp::HYBRID)
- {
- result = encode_hybrid(point);
- }
- else
- {
- throw Invalid_Argument("illegal point encoding format specification");
- }
- return result;
- }
-SecureVector<byte> encode_compressed(const PointGFp& point)
- {
-
-
- if(point.is_zero())
- {
- SecureVector<byte> result (1);
- result[0] = 0;
- return result;
-
- }
- u32bit l = point.get_curve().get_p().bits();
- int dummy = l & 7;
- if(dummy != 0)
- {
- l += 8 - dummy;
- }
- l /= 8;
- SecureVector<byte> result (l+1);
- result[0] = 2;
- BigInt x = point.get_affine_x().get_value();
- SecureVector<byte> bX = BigInt::encode_1363(x, l);
- result.copy(1, bX.begin(), bX.size());
- BigInt y = point.get_affine_y().get_value();
- if(y.get_bit(0))
- {
- result[0] |= 1;
- }
- return result;
- }
-
-
-SecureVector<byte> encode_uncompressed(const PointGFp& point)
- {
- if(point.is_zero())
- {
- SecureVector<byte> result (1);
- result[0] = 0;
- return result;
- }
- u32bit l = point.get_curve().get_p().bits();
- int dummy = l & 7;
- if(dummy != 0)
- {
- l += 8 - dummy;
- }
- l /= 8;
- SecureVector<byte> result (2*l+1);
- result[0] = 4;
- BigInt x = point.get_affine_x().get_value();
- BigInt y = point.get_affine_y().get_value();
- SecureVector<byte> bX = BigInt::encode_1363(x, l);
- SecureVector<byte> bY = BigInt::encode_1363(y, l);
- result.copy(1, bX.begin(), l);
- result.copy(l+1, bY.begin(), l);
- return result;
-
- }
-
-SecureVector<byte> encode_hybrid(const PointGFp& point)
- {
- if(point.is_zero())
- {
- SecureVector<byte> result (1);
- result[0] = 0;
- return result;
- }
- u32bit l = point.get_curve().get_p().bits();
- int dummy = l & 7;
- if(dummy != 0)
- {
- l += 8 - dummy;
- }
- l /= 8;
- SecureVector<byte> result (2*l+1);
- result[0] = 6;
- BigInt x = point.get_affine_x().get_value();
- BigInt y = point.get_affine_y().get_value();
- SecureVector<byte> bX = BigInt::encode_1363(x, l);
- SecureVector<byte> bY = BigInt::encode_1363(y, l);
- result.copy(1, bX.begin(), bX.size());
- result.copy(l+1, bY.begin(), bY.size());
- if(y.get_bit(0))
- {
- result[0] |= 1;
- }
- return result;
- }
-
-PointGFp OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve)
- {
- if(os.size() == 1 && os[0] == 0)
- {
- return PointGFp(curve); // return zero
- }
- SecureVector<byte> bX;
- SecureVector<byte> bY;
-
- GFpElement x(1,0);
- GFpElement y(1,0);
- GFpElement z(1,0);
-
- const byte pc = os[0];
- BigInt bi_dec_x;
- BigInt bi_dec_y;
- switch (pc)
- {
- case 2:
- case 3:
- //compressed form
- bX = SecureVector<byte>(os.size() - 1);
- bX.copy(os.begin()+1, os.size()-1);
-
- bi_dec_x = BigInt::decode(bX, bX.size());
- x = GFpElement(curve.get_p(), bi_dec_x);
- bool yMod2;
- yMod2 = (pc & 1) == 1;
- y = PointGFp::decompress(yMod2, x, curve);
- break;
- case 4:
- // uncompressed form
- int l;
- l = (os.size() -1)/2;
- bX = SecureVector<byte>(l);
- bY = SecureVector<byte>(l);
- bX.copy(os.begin()+1, l);
- bY.copy(os.begin()+1+l, l);
- bi_dec_x = BigInt::decode(bX.begin(), bX.size());
-
- bi_dec_y = BigInt::decode(bY.begin(),bY.size());
- x = GFpElement(curve.get_p(), bi_dec_x);
- y = GFpElement(curve.get_p(), bi_dec_y);
- break;
-
- case 6:
- case 7:
- //hybrid form
- l = (os.size() - 1)/2;
- bX = SecureVector<byte>(l);
- bY = SecureVector<byte>(l);
- bX.copy(os.begin() + 1, l);
- bY.copy(os.begin()+1+l, l);
- yMod2 = (pc & 0x01) == 1;
- if(!(PointGFp::decompress(yMod2, x, curve) == y))
- {
- throw Illegal_Point("error during decoding hybrid format");
- }
- break;
- default:
- throw Invalid_Argument("encountered illegal format specification while decoding point");
- }
- z = GFpElement(curve.get_p(), BigInt(1));
- //assert((x.is_trf_to_mres() && x.is_use_montgm()) || !x.is_trf_to_mres());
- //assert((y.is_trf_to_mres() && y.is_use_montgm()) || !y.is_trf_to_mres());
- //assert((z.is_trf_to_mres() && z.is_use_montgm()) || !z.is_trf_to_mres());
- PointGFp result(curve, x, y, z);
- result.check_invariants();
- //assert((result.get_jac_proj_x().is_trf_to_mres() && result.get_jac_proj_x().is_use_montgm()) || !result.get_jac_proj_x().is_trf_to_mres());
- //assert((result.get_jac_proj_y().is_trf_to_mres() && result.get_jac_proj_y().is_use_montgm()) || !result.get_jac_proj_y().is_trf_to_mres());
- //assert((result.get_jac_proj_z().is_trf_to_mres() && result.get_jac_proj_z().is_use_montgm()) || !result.get_jac_proj_z().is_trf_to_mres());
- return result;
- }
-
-GFpElement PointGFp::decompress(bool yMod2, const GFpElement& x,
- const CurveGFp& curve)
- {
- BigInt xVal = x.get_value();
- BigInt xpow3 = xVal * xVal * xVal;
- BigInt g = curve.get_a().get_value() * xVal;
- g += xpow3;
- g += curve.get_b().get_value();
- g = g%curve.get_p();
- BigInt z = ressol(g, curve.get_p());
-
- if(z < 0)
- throw Illegal_Point("error during decompression");
-
- bool zMod2 = z.get_bit(0);
- if((zMod2 && ! yMod2) || (!zMod2 && yMod2))
- {
- z = curve.get_p() - z;
- }
- return GFpElement(curve.get_p(),z);
- }
-
-PointGFp create_random_point(RandomNumberGenerator& rng,
- const CurveGFp& curve)
- {
-
- // create a random point
- GFpElement mX(1,1);
- GFpElement mY(1,1);
- GFpElement mZ(1,1);
- GFpElement minusOne(curve.get_p(), BigInt(BigInt::Negative,1));
- mY = minusOne;
- GFpElement y2(1,1);
- GFpElement x(1,1);
-
- while (mY == minusOne)
- {
- BigInt value(rng, curve.get_p().bits());
- mX = GFpElement(curve.get_p(),value);
- y2 = curve.get_a() * mX;
- x = mX * mX;
- x *= mX;
- y2 += (x + curve.get_b());
-
- value = ressol(y2.get_value(), curve.get_p());
-
- if(value < 0)
- mY = minusOne;
- else
- mY = GFpElement(curve.get_p(), value);
- }
- mZ = GFpElement(curve.get_p(), BigInt(1));
-
- return PointGFp(curve, mX, mY, mZ);
- }
-
-} // namespace Botan
diff --git a/src/math/gfpmath/point_gfp.h b/src/math/gfpmath/point_gfp.h
deleted file mode 100644
index 276635f56..000000000
--- a/src/math/gfpmath/point_gfp.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
-* Arithmetic for point groups of elliptic curves over GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_POINT_GFP_H__
-#define BOTAN_POINT_GFP_H__
-
-#include <botan/curve_gfp.h>
-#include <vector>
-
-namespace Botan {
-
-struct BOTAN_DLL Illegal_Point : public Exception
- {
- Illegal_Point(const std::string& err = "") : Exception(err) {}
- };
-
-/**
-* This class represents one point on a curve of GF(p)
-*/
-class BOTAN_DLL PointGFp
- {
- public:
- /**
- * uncompressed encoding byte value
- */
- static const int UNCOMPRESSED = 0;
-
- /**
- * compressed encoding byte value
- */
- static const int COMPRESSED = 1;
-
- /**
- * hybrid encoding byte value
- */
- static const int HYBRID = 2;
-
- /**
- * Construct the point O
- * @param curve The base curve
- */
- PointGFp(const CurveGFp& curve);
-
- /**
- * Construct a point given its affine coordinates
- * @param curve the base curve
- * @param x affine x coordinate
- * @param y affine y coordinate
- */
- PointGFp(const CurveGFp& curve,
- const GFpElement& x,
- const GFpElement& y);
-
- /**
- * Construct a point given its jacobian projective coordinates
- * @param curve the base curve
- * @param x jacobian projective x coordinate
- * @param y jacobian projective y coordinate
- * @param z jacobian projective y coordinate
- */
- PointGFp(const CurveGFp& curve,
- const GFpElement& x,
- const GFpElement& y,
- const GFpElement& z);
-
- //PointGFp(const PointGFp& other) = default;
- //PointGFp& operator=(const PointGFp& other) = default;
-
- /**
- * += Operator
- * @param rhs the PointGFp to add to the local value
- * @result resulting PointGFp
- */
- PointGFp& operator+=(const PointGFp& rhs);
-
- /**
- * -= Operator
- * @param rhs the PointGFp to subtract from the local value
- * @result resulting PointGFp
- */
- PointGFp& operator-=(const PointGFp& rhs);
-
- /**
- * *= Operator
- * This function turns on the the special reduction multiplication
- * itself for fast computation, turns it off again when finished.
- * @param scalar the PointGFp to multiply with *this
- * @result resulting PointGFp
- */
- PointGFp& operator*=(const BigInt& scalar);
-
- /**
- * the equivalent to operator*= with countermeasures against
- * sidechannel attacks, using the randomized exponent
- * and add-and-double-always
- * countermeasures (suitable for ECDSA and ECKAEG)
- * @param scalar the scalar to multiply the point with
- * @param point_order a multiple of the order of the point
- *(= n * k in the general case; k is the cofactor)
- * @param max_secr the maximal size of the scalar
- * (will usually be n-1 )
- * @result resulting PointGFp
- */
- PointGFp& mult_this_secure(const BigInt& scalar,
- const BigInt& point_order,
- const BigInt& max_secr);
-
- /**
- * Negate internal value(*this *= -1 )
- * @return *this
- */
- PointGFp& negate();
-
- /**
- * Multiply the point by two(*this *= 2 )
- * @return *this
- */
- PointGFp& mult2_in_place();
-
- /**
- * Set z coordinate to one.
- * @return *this
- */
- const PointGFp& set_z_to_one() const;
-
- /**
- * Turn on the special reduction multiplication (i.e. the
- * Montgomery multiplication in the current implementation) for
- * the coordinates. This enables fast execution of mult2_in_place()
- * and operator+=().
- */
- void turn_on_sp_red_mul() const;
-
- /**
- * Return a point
- * where the coordinates are transformed
- * so that z equals one,
- * thus x and y have just the affine values.
- * @result *this
- */
- PointGFp get_z_to_one() const;
-
- /**
- * Return base curve of this point
- * @result the curve over GF(p) of this point
- */
- const CurveGFp& get_curve() const { return mC; }
-
- /**
- * get affine x coordinate
- * @result affine x coordinate
- */
- GFpElement get_affine_x() const;
-
- /**
- * get affine y coordinate
- * @result affine y coordinate
- */
- GFpElement get_affine_y() const;
-
- /**
- * get the jacobian projective x coordinate
- * @result jacobian projective x coordinate
- */
- GFpElement get_jac_proj_x() const;
-
- /**
- * get the jacobian projective y coordinate
- * @result jacobian projective y coordinate
- */
- GFpElement get_jac_proj_y() const;
-
- /**
- * get the jacobian projective z coordinate
- * @result jacobian projective z coordinate
- */
- GFpElement get_jac_proj_z() const;
-
- /**
- * Is this the point at infinity?
- * @result true, if this point is at infinity, false otherwise.
- */
- bool is_zero() const;
-
- /**
- * Checks whether the point is to be found on the underlying curve.
- * Throws an Invalid_Point exception in case of detecting that the point
- * does not satisfy the curve equation.
- * To be used to ensure against fault attacks.
- */
- void check_invariants() const;
-
- /**
- * swaps the states of *this and other, does not throw!
- * @param other the object to swap values with
- */
- void swap(PointGFp& other);
-
- static GFpElement decompress(bool yMod2, GFpElement const& x, const CurveGFp& curve);
-
- private:
- CurveGFp mC;
- mutable GFpElement mX; // NOTE: these values must be mutable (affine<->proj)
- mutable GFpElement mY;
- mutable GFpElement mZ;
- };
-
-// relational operators
-bool BOTAN_DLL operator==(const PointGFp& lhs, const PointGFp& rhs);
-inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs )
- {
- return !operator==(lhs, rhs);
- }
-
-// arithmetic operators
-PointGFp BOTAN_DLL operator+(const PointGFp& lhs, const PointGFp& rhs);
-PointGFp BOTAN_DLL operator-(const PointGFp& lhs, const PointGFp& rhs);
-PointGFp BOTAN_DLL operator-(const PointGFp& lhs);
-
-PointGFp BOTAN_DLL operator*(const BigInt& scalar, const PointGFp& point);
-PointGFp BOTAN_DLL operator*(const PointGFp& point, const BigInt& scalar);
-PointGFp BOTAN_DLL mult_point_secure(const PointGFp& point,
- const BigInt& scalar,
- const BigInt& point_order,
- const BigInt& max_secret);
-
-PointGFp BOTAN_DLL mult2(const PointGFp& point);
-
-PointGFp BOTAN_DLL create_random_point(RandomNumberGenerator& rng,
- const CurveGFp& curve);
-
-// encoding and decoding
-SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format);
-PointGFp BOTAN_DLL OS2ECP(MemoryRegion<byte> const& os, const CurveGFp& curve);
-
-/* Should these be private? */
-SecureVector<byte>
-BOTAN_DLL encode_uncompressed(const PointGFp& point);
-
-SecureVector<byte> BOTAN_DLL encode_hybrid(const PointGFp& point);
-SecureVector<byte> BOTAN_DLL encode_compressed(const PointGFp& point);
-
-// swaps the states of point1 and point2, does not throw!
-// cf. Meyers, Item 25
-inline
-void swap(PointGFp& point1, PointGFp& point2 )
- {
- point1.swap(point2);
- }
-
-} // namespace Botan
-
-namespace std {
-
-// swaps the states of point1 and point2, does not throw!
-// cf. Meyers, Item 25
-template<> inline void
-swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y) { x.swap(y); }
-
-} // namespace std
-
-#endif
diff --git a/src/math/numbertheory/curve_gfp.h b/src/math/numbertheory/curve_gfp.h
new file mode 100644
index 000000000..697065dfe
--- /dev/null
+++ b/src/math/numbertheory/curve_gfp.h
@@ -0,0 +1,96 @@
+/*
+* Elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_GFP_CURVE_H__
+#define BOTAN_GFP_CURVE_H__
+
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+namespace Botan {
+
+/**
+* This class represents an elliptic curve over GF(p)
+*/
+class BOTAN_DLL CurveGFp
+ {
+ public:
+
+ /**
+ * Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
+ * @param p prime number of the field
+ * @param a first coefficient
+ * @param b second coefficient
+ */
+ CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) :
+ p(p), a(a), b(b), reducer_p(p) {}
+
+ // CurveGFp(const CurveGFp& other) = default;
+ // CurveGFp& operator=(const CurveGFp& other) = default;
+
+ /**
+ * Get coefficient a
+ * @result coefficient a
+ */
+ const BigInt& get_a() const { return a; }
+
+ /**
+ * Get coefficient b
+ * @result coefficient b
+ */
+ const BigInt& get_b() const { return b; }
+
+ /**
+ * Get prime modulus of the field of the curve
+ * @result prime modulus of the field of the curve
+ */
+ const BigInt& get_p() const { return p; }
+
+ const Modular_Reducer& mod_p() const { return reducer_p; }
+
+ /**
+ * swaps the states of *this and other, does not throw
+ * @param other The curve to swap values with
+ */
+ void swap(CurveGFp& other)
+ {
+ std::swap(a, other.a);
+ std::swap(b, other.b);
+ std::swap(p, other.p);
+ }
+
+ bool operator==(const CurveGFp& other) const
+ {
+ return (p == other.p && a == other.a && b == other.b);
+ }
+
+ private:
+ BigInt p, a, b;
+ Modular_Reducer reducer_p;
+ };
+
+inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+}
+
+namespace std {
+
+template<> inline
+void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
+ Botan::CurveGFp& curve2)
+ {
+ curve1.swap(curve2);
+ }
+
+} // namespace std
+
+#endif
diff --git a/src/math/numbertheory/info.txt b/src/math/numbertheory/info.txt
index 19abfaaa0..58851e055 100644
--- a/src/math/numbertheory/info.txt
+++ b/src/math/numbertheory/info.txt
@@ -4,7 +4,9 @@ define BIGINT_MATH
<header:public>
blinding.h
+curve_gfp.h
numthry.h
+point_gfp.h
pow_mod.h
reducer.h
</header:public>
@@ -20,6 +22,7 @@ jacobi.cpp
make_prm.cpp
mp_numth.cpp
numthry.cpp
+point_gfp.cpp
pow_mod.cpp
powm_fw.cpp
powm_mnt.cpp
diff --git a/src/math/numbertheory/numthry.cpp b/src/math/numbertheory/numthry.cpp
index 760250712..f79fdec2b 100644
--- a/src/math/numbertheory/numthry.cpp
+++ b/src/math/numbertheory/numthry.cpp
@@ -1,11 +1,12 @@
/*
* Number Theory Functions
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/numthry.h>
+#include <botan/reducer.h>
#include <botan/internal/bit_ops.h>
#include <algorithm>
@@ -14,6 +15,62 @@ namespace Botan {
namespace {
/*
+* Miller-Rabin Primality Tester
+*/
+class MillerRabin_Test
+ {
+ public:
+ bool passes_test(const BigInt& nonce);
+ MillerRabin_Test(const BigInt& num);
+ private:
+ BigInt n, r, n_minus_1;
+ u32bit s;
+ Fixed_Exponent_Power_Mod pow_mod;
+ Modular_Reducer reducer;
+ };
+
+/*
+* Miller-Rabin Test
+*/
+bool MillerRabin_Test::passes_test(const BigInt& a)
+ {
+ if(a < 2 || a >= n_minus_1)
+ throw Invalid_Argument("Bad size for nonce in Miller-Rabin test");
+
+ BigInt y = pow_mod(a);
+ if(y == 1 || y == n_minus_1)
+ return true;
+
+ for(u32bit i = 1; i != s; ++i)
+ {
+ y = reducer.square(y);
+
+ if(y == 1)
+ return false;
+ if(y == n_minus_1)
+ return true;
+ }
+ return false;
+ }
+
+/*
+* Miller-Rabin Constructor
+*/
+MillerRabin_Test::MillerRabin_Test(const BigInt& num)
+ {
+ if(num.is_even() || num < 3)
+ throw Invalid_Argument("MillerRabin_Test: Invalid number for testing");
+
+ n = num;
+ n_minus_1 = n - 1;
+ s = low_zero_bits(n_minus_1);
+ r = n_minus_1 >> s;
+
+ pow_mod = Fixed_Exponent_Power_Mod(r, n);
+ reducer = Modular_Reducer(n);
+ }
+
+/*
* Miller-Rabin Iterations
*/
u32bit miller_rabin_test_iterations(u32bit bits, bool verify)
@@ -300,45 +357,4 @@ bool passes_mr_tests(RandomNumberGenerator& rng,
return true;
}
-/*
-* Miller-Rabin Test
-*/
-bool MillerRabin_Test::passes_test(const BigInt& a)
- {
- if(a < 2 || a >= n_minus_1)
- throw Invalid_Argument("Bad size for nonce in Miller-Rabin test");
-
- BigInt y = pow_mod(a);
- if(y == 1 || y == n_minus_1)
- return true;
-
- for(u32bit i = 1; i != s; ++i)
- {
- y = reducer.square(y);
-
- if(y == 1)
- return false;
- if(y == n_minus_1)
- return true;
- }
- return false;
- }
-
-/*
-* Miller-Rabin Constructor
-*/
-MillerRabin_Test::MillerRabin_Test(const BigInt& num)
- {
- if(num.is_even() || num < 3)
- throw Invalid_Argument("MillerRabin_Test: Invalid number for testing");
-
- n = num;
- n_minus_1 = n - 1;
- s = low_zero_bits(n_minus_1);
- r = n_minus_1 >> s;
-
- pow_mod = Fixed_Exponent_Power_Mod(r, n);
- reducer = Modular_Reducer(n);
- }
-
}
diff --git a/src/math/numbertheory/numthry.h b/src/math/numbertheory/numthry.h
index ae2c219fc..080f184a4 100644
--- a/src/math/numbertheory/numthry.h
+++ b/src/math/numbertheory/numthry.h
@@ -9,7 +9,6 @@
#define BOTAN_NUMBER_THEORY_H__
#include <botan/bigint.h>
-#include <botan/reducer.h>
#include <botan/pow_mod.h>
#include <botan/rng.h>
@@ -100,21 +99,6 @@ const u32bit PRIME_PRODUCTS_TABLE_SIZE = 256;
extern const u16bit BOTAN_DLL PRIMES[];
extern const u64bit PRIME_PRODUCTS[];
-/*
-* Miller-Rabin Primality Tester
-*/
-class BOTAN_DLL MillerRabin_Test
- {
- public:
- bool passes_test(const BigInt&);
- MillerRabin_Test(const BigInt&);
- private:
- BigInt n, r, n_minus_1;
- u32bit s;
- Fixed_Exponent_Power_Mod pow_mod;
- Modular_Reducer reducer;
- };
-
}
#endif
diff --git a/src/math/numbertheory/point_gfp.cpp b/src/math/numbertheory/point_gfp.cpp
new file mode 100644
index 000000000..06c42d18c
--- /dev/null
+++ b/src/math/numbertheory/point_gfp.cpp
@@ -0,0 +1,423 @@
+/*
+* Arithmetic for point groups of elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/point_gfp.h>
+#include <botan/numthry.h>
+
+namespace Botan {
+
+namespace {
+
+BigInt decompress_point(bool yMod2,
+ const BigInt& x,
+ const CurveGFp& curve)
+ {
+ BigInt xpow3 = x * x * x;
+
+ BigInt g = curve.get_a() * x;
+ g += xpow3;
+ g += curve.get_b();
+ g = g % curve.get_p();
+
+ BigInt z = ressol(g, curve.get_p());
+
+ if(z < 0)
+ throw Illegal_Point("error during decompression");
+
+ if(z.get_bit(0) != yMod2)
+ z = curve.get_p() - z;
+
+ return z;
+ }
+
+}
+
+// arithmetic operators
+PointGFp& PointGFp::operator+=(const PointGFp& rhs)
+ {
+ if(rhs.is_zero())
+ return *this;
+
+ if(is_zero())
+ {
+ *this = rhs;
+ return *this;
+ }
+
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt rhs_z2 = mod_p.square(rhs.coord_z);
+ BigInt U1 = mod_p.multiply(coord_x, rhs_z2);
+ BigInt S1 = mod_p.multiply(coord_y, mod_p.multiply(rhs.coord_z, rhs_z2));
+
+ BigInt lhs_z2 = mod_p.square(coord_z);
+ BigInt U2 = mod_p.multiply(rhs.coord_x, lhs_z2);
+ BigInt S2 = mod_p.multiply(rhs.coord_y, mod_p.multiply(coord_z, lhs_z2));
+
+ BigInt H = mod_p.reduce(U2 - U1);
+ BigInt r = mod_p.reduce(S2 - S1);
+
+ if(H.is_zero())
+ {
+ if(r.is_zero())
+ {
+ mult2_in_place();
+ return *this;
+ }
+
+ *this = PointGFp(curve); // setting myself to zero
+ return *this;
+ }
+
+ U2 = mod_p.square(H);
+
+ S2 = mod_p.multiply(U2, H);
+
+ U2 = mod_p.multiply(U1, U2);
+
+ BigInt x = mod_p.reduce(mod_p.square(r) - S2 - mod_p.multiply(2, U2));
+ BigInt y = mod_p.reduce(mod_p.multiply(r, (U2-x)) - mod_p.multiply(S1, S2));
+ BigInt z = mod_p.multiply(mod_p.multiply(coord_z, rhs.coord_z), H);
+
+ coord_x = x;
+ coord_y = y;
+ coord_z = z;
+
+ return *this;
+ }
+
+PointGFp& PointGFp::operator-=(const PointGFp& rhs)
+ {
+ PointGFp minus_rhs = PointGFp(rhs).negate();
+
+ if(is_zero())
+ *this = minus_rhs;
+ else
+ *this += minus_rhs;
+
+ return *this;
+ }
+
+PointGFp& PointGFp::operator*=(const BigInt& scalar)
+ {
+ if(scalar.abs() <= 2) // special cases for small values
+ {
+ u32bit value = scalar.abs().to_u32bit();
+
+ if(value == 0)
+ *this = PointGFp(curve); // set to zero point
+ else if(value == 1)
+ {
+ if(scalar.is_negative())
+ this->negate();
+ }
+ else if(value == 2)
+ {
+ this->mult2_in_place();
+ if(scalar.is_negative())
+ this->negate();
+ }
+
+ return *this;
+ }
+
+ PointGFp H(this->curve); // create as zero
+ PointGFp P(*this);
+
+ if(scalar.is_negative())
+ P.negate();
+
+ for(int i = scalar.bits() - 1; i >= 0; --i)
+ {
+ H.mult2_in_place();
+ if(scalar.get_bit(i))
+ H += P;
+ }
+
+ if(!H.is_zero()) // cannot convert if H == O
+ {
+ /**
+ * Convert H to an equivalent point with z == 1, thus x and y
+ * correspond to their affine coordinates
+ */
+ if(H.coord_z != 1)
+ {
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt z_inv = inverse_mod(H.coord_z, curve.get_p());
+
+ BigInt z_inv_2 = mod_p.square(z_inv);
+
+ H.coord_x = mod_p.multiply(H.coord_x, z_inv_2);
+ H.coord_y = mod_p.multiply(H.coord_y, mod_p.multiply(z_inv, z_inv_2));
+ H.coord_z = 1;
+ }
+ }
+
+ *this = H;
+ return *this;
+ }
+
+PointGFp& PointGFp::negate()
+ {
+ if(!is_zero())
+ coord_y = curve.get_p() - coord_y;
+
+ return *this;
+ }
+
+// *this *= 2
+void PointGFp::mult2_in_place()
+ {
+ if(is_zero())
+ return;
+ else if(coord_y.is_zero())
+ {
+ *this = PointGFp(curve); // setting myself to zero
+ return;
+ }
+
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt y_2 = mod_p.square(coord_y);
+
+ BigInt S = mod_p.multiply(4, mod_p.multiply(coord_x, y_2));
+
+ BigInt a_z4 = mod_p.multiply(curve.get_a(),
+ mod_p.square(mod_p.square(coord_z)));
+
+ BigInt M = mod_p.reduce(a_z4 + 3 * mod_p.square(coord_x));
+
+ BigInt x = mod_p.reduce(mod_p.square(M) - mod_p.multiply(2, S));
+
+ BigInt y = mod_p.square(y_2);
+
+ BigInt z = mod_p.multiply(2, mod_p.reduce(y + y));
+
+ BigInt U = mod_p.reduce(z + z);
+
+ y = mod_p.reduce(mod_p.multiply(M, S - x) - U);
+
+ z = mod_p.multiply(2, mod_p.multiply(coord_y, coord_z));
+
+ coord_x = x;
+ coord_y = y;
+ coord_z = z;
+ }
+
+BigInt PointGFp::get_affine_x() const
+ {
+ if(is_zero())
+ throw Illegal_Transformation("cannot convert to affine");
+
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt z2 = mod_p.square(coord_z);
+ return mod_p.multiply(coord_x, inverse_mod(z2, curve.get_p()));
+ }
+
+BigInt PointGFp::get_affine_y() const
+ {
+ if(is_zero())
+ throw Illegal_Transformation("cannot convert to affine");
+
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt z3 = mod_p.cube(coord_z);
+ return mod_p.multiply(coord_y, inverse_mod(z3, curve.get_p()));
+ }
+
+// Is this the point at infinity?
+bool PointGFp::is_zero() const
+ {
+ return(coord_x.is_zero() && coord_z.is_zero());
+ }
+
+void PointGFp::check_invariants() const
+ {
+ /*
+ Is the point still on the curve?? (If everything is correct, the
+ point is always on its curve; then the function will return
+ silently. If Oskar managed to corrupt this object's state, then it
+ will throw an exception.)
+ */
+
+ if(is_zero())
+ return;
+
+ const Modular_Reducer& mod_p = curve.mod_p();
+
+ BigInt y2 = mod_p.square(coord_y);
+ BigInt x3 = mod_p.cube(coord_x);
+
+ BigInt ax = mod_p.multiply(coord_x, curve.get_a());
+
+ if(coord_z == 1)
+ {
+ if(mod_p.reduce(x3 + ax + curve.get_b()) != y2)
+ throw Illegal_Point("Invalid ECP point: y^2 != x^3 + a*x + b");
+ }
+
+ BigInt z2 = mod_p.square(coord_z);
+ BigInt z3 = mod_p.multiply(coord_z, z2);
+
+ BigInt ax_z4 = mod_p.multiply(mod_p.multiply(z3, coord_z), ax);
+
+ BigInt b_z6 = mod_p.multiply(curve.get_b(), mod_p.square(z3));
+
+ if(y2 != mod_p.reduce(x3 + ax_z4 + b_z6))
+ throw Illegal_Point("Invalid ECP point: y^2 != x^3 + a*x*z^4 + b*z^6");
+ }
+
+// swaps the states of *this and other, does not throw!
+void PointGFp::swap(PointGFp& other)
+ {
+ curve.swap(other.curve);
+ coord_x.swap(other.coord_x);
+ coord_y.swap(other.coord_y);
+ coord_z.swap(other.coord_z);
+ }
+
+bool PointGFp::operator==(const PointGFp& other) const
+ {
+ return (coord_x == other.coord_x &&
+ coord_y == other.coord_y &&
+ coord_z == other.coord_z &&
+ get_curve() == other.get_curve());
+ }
+
+// arithmetic operators
+PointGFp operator+(const PointGFp& lhs, PointGFp const& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp += rhs;
+ }
+
+PointGFp operator-(const PointGFp& lhs, PointGFp const& rhs)
+ {
+ PointGFp tmp(lhs);
+ return tmp -= rhs;
+ }
+
+PointGFp operator-(const PointGFp& lhs)
+ {
+ return PointGFp(lhs).negate();
+ }
+
+PointGFp operator*(const BigInt& scalar, const PointGFp& point)
+ {
+ PointGFp result(point);
+ return result *= scalar;
+ }
+
+PointGFp operator*(const PointGFp& point, const BigInt& scalar)
+ {
+ PointGFp result(point);
+ return result *= scalar;
+ }
+
+// encoding and decoding
+SecureVector<byte> EC2OSP(const PointGFp& point, byte format)
+ {
+ if(point.is_zero())
+ return SecureVector<byte>(1); // single 0 byte
+
+ const u32bit p_bytes = point.get_curve().get_p().bytes();
+
+ BigInt x = point.get_affine_x();
+ BigInt y = point.get_affine_y();
+
+ SecureVector<byte> bX = BigInt::encode_1363(x, p_bytes);
+ SecureVector<byte> bY = BigInt::encode_1363(y, p_bytes);
+
+ if(format == PointGFp::UNCOMPRESSED)
+ {
+ SecureVector<byte> result(2*p_bytes+1);
+ result[0] = 4;
+
+ result.copy(1, bX.begin(), p_bytes);
+ result.copy(p_bytes+1, bY.begin(), p_bytes);
+ return result;
+ }
+ else if(format == PointGFp::COMPRESSED)
+ {
+ SecureVector<byte> result(p_bytes+1);
+ result[0] = 2;
+
+ result.copy(1, bX.begin(), bX.size());
+
+ if(y.get_bit(0))
+ result[0] |= 1;
+
+ return result;
+ }
+ else if(format == PointGFp::HYBRID)
+ {
+ SecureVector<byte> result(2*p_bytes+1);
+ result[0] = 6;
+
+ result.copy(1, bX.begin(), bX.size());
+ result.copy(p_bytes+1, bY.begin(), bY.size());
+
+ if(y.get_bit(0))
+ result[0] |= 1;
+
+ return result;
+ }
+ else
+ throw Invalid_Argument("illegal point encoding format specification");
+ }
+
+PointGFp OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve)
+ {
+ if(os.size() == 1 && os[0] == 0)
+ return PointGFp(curve); // return zero
+
+ const byte pc = os[0];
+
+ BigInt x, y;
+
+ if(pc == 2 || pc == 3)
+ {
+ //compressed form
+ x = BigInt::decode(&os[1], os.size() - 1);
+
+ bool yMod2 = ((pc & 0x01) == 1);
+ y = decompress_point(yMod2, x, curve);
+ }
+ else if(pc == 4)
+ {
+ // uncompressed form
+ u32bit l = (os.size() - 1) / 2;
+
+ x = BigInt::decode(&os[1], l);
+ y = BigInt::decode(&os[l+1], l);
+ }
+ else if(pc == 6 || pc == 7)
+ {
+ // hybrid form
+ u32bit l = (os.size() - 1) / 2;
+
+ x = BigInt::decode(&os[1], l);
+ y = BigInt::decode(&os[l+1], l);
+
+ bool yMod2 = ((pc & 0x01) == 1);
+
+ if(decompress_point(yMod2, x, curve) != y)
+ throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
+ }
+ else
+ throw Invalid_Argument("OS2ECP: Unknown format type");
+
+ PointGFp result(curve, x, y);
+ result.check_invariants();
+ return result;
+ }
+
+}
diff --git a/src/math/numbertheory/point_gfp.h b/src/math/numbertheory/point_gfp.h
new file mode 100644
index 000000000..0741b5e56
--- /dev/null
+++ b/src/math/numbertheory/point_gfp.h
@@ -0,0 +1,201 @@
+/*
+* Arithmetic for point groups of elliptic curves over GF(p)
+*
+* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
+* 2008-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_POINT_GFP_H__
+#define BOTAN_POINT_GFP_H__
+
+#include <botan/curve_gfp.h>
+#include <vector>
+
+namespace Botan {
+
+struct BOTAN_DLL Illegal_Transformation : public Exception
+ {
+ Illegal_Transformation(const std::string& err =
+ "Requested transformation is not possible") :
+ Exception(err) {}
+ };
+
+struct BOTAN_DLL Illegal_Point : public Exception
+ {
+ Illegal_Point(const std::string& err = "Malformed ECP point detected") :
+ Exception(err) {}
+ };
+
+/**
+* This class represents one point on a curve of GF(p)
+*/
+class BOTAN_DLL PointGFp
+ {
+ public:
+ enum Compression_Type {
+ UNCOMPRESSED = 0,
+ COMPRESSED = 1,
+ HYBRID = 2
+ };
+
+ /**
+ * Construct the point O
+ * @param curve The base curve
+ */
+ PointGFp(const CurveGFp& curve) :
+ curve(curve), coord_x(0), coord_y(1), coord_z(0) {}
+
+ /**
+ * Construct a point given its affine coordinates
+ * @param curve the base curve
+ * @param x affine x coordinate
+ * @param y affine y coordinate
+ */
+ PointGFp(const CurveGFp& curve,
+ const BigInt& x, const BigInt& y) :
+ curve(curve), coord_x(x), coord_y(y), coord_z(1) {}
+
+ /**
+ * Construct a point given its jacobian projective coordinates
+ * @param curve the base curve
+ * @param x jacobian projective x coordinate
+ * @param y jacobian projective y coordinate
+ * @param z jacobian projective z coordinate
+ */
+ PointGFp(const CurveGFp& curve,
+ const BigInt& x, const BigInt& y, const BigInt& z) :
+ curve(curve), coord_x(x), coord_y(y), coord_z(z) {}
+
+ //PointGFp(const PointGFp& other) = default;
+ //PointGFp& operator=(const PointGFp& other) = default;
+
+ /**
+ * += Operator
+ * @param rhs the PointGFp to add to the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator+=(const PointGFp& rhs);
+
+ /**
+ * -= Operator
+ * @param rhs the PointGFp to subtract from the local value
+ * @result resulting PointGFp
+ */
+ PointGFp& operator-=(const PointGFp& rhs);
+
+ /**
+ * *= Operator
+ * This function turns on the the special reduction multiplication
+ * itself for fast computation, turns it off again when finished.
+ * @param scalar the PointGFp to multiply with *this
+ * @result resulting PointGFp
+ */
+ PointGFp& operator*=(const BigInt& scalar);
+
+ /**
+ * Negate this point
+ * @return *this
+ */
+ PointGFp& negate();
+
+ /**
+ * Return base curve of this point
+ * @result the curve over GF(p) of this point
+ */
+ const CurveGFp& get_curve() const { return curve; }
+
+ /**
+ * get affine x coordinate
+ * @result affine x coordinate
+ */
+ BigInt get_affine_x() const;
+
+ /**
+ * get affine y coordinate
+ * @result affine y coordinate
+ */
+ BigInt get_affine_y() const;
+
+ /**
+ * get the jacobian projective x coordinate
+ * @result jacobian projective x coordinate
+ */
+ const BigInt& get_jac_proj_x() const { return coord_x; }
+
+ /**
+ * get the jacobian projective y coordinate
+ * @result jacobian projective y coordinate
+ */
+ const BigInt& get_jac_proj_y() const { return coord_y; }
+
+ /**
+ * get the jacobian projective z coordinate
+ * @result jacobian projective z coordinate
+ */
+ const BigInt& get_jac_proj_z() const { return coord_z; }
+
+ /**
+ * Is this the point at infinity?
+ * @result true, if this point is at infinity, false otherwise.
+ */
+ bool is_zero() const;
+
+ /**
+ * Checks whether the point is to be found on the underlying curve.
+ * Throws an Invalid_Point exception in case of detecting that the point
+ * does not satisfy the curve equation.
+ * To be used to ensure against fault attacks.
+ */
+ void check_invariants() const;
+
+ /**
+ * swaps the states of *this and other, does not throw!
+ * @param other the object to swap values with
+ */
+ void swap(PointGFp& other);
+
+ /**
+ * Equality operator
+ */
+ bool operator==(const PointGFp& other) const;
+ private:
+ /**
+ * Multiply the point by two
+ */
+ void mult2_in_place();
+
+ CurveGFp curve;
+ BigInt coord_x, coord_y, coord_z;
+ };
+
+// relational operators
+inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs)
+ {
+ return !(rhs == lhs);
+ }
+
+// arithmetic operators
+PointGFp BOTAN_DLL operator+(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp BOTAN_DLL operator-(const PointGFp& lhs, const PointGFp& rhs);
+PointGFp BOTAN_DLL operator-(const PointGFp& lhs);
+
+PointGFp BOTAN_DLL operator*(const BigInt& scalar, const PointGFp& point);
+PointGFp BOTAN_DLL operator*(const PointGFp& point, const BigInt& scalar);
+
+// encoding and decoding
+SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format);
+PointGFp BOTAN_DLL OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve);
+
+}
+
+namespace std {
+
+template<>
+inline void swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y)
+ { x.swap(y); }
+
+}
+
+#endif
diff --git a/src/math/numbertheory/reducer.cpp b/src/math/numbertheory/reducer.cpp
index aa53f1a0e..257ece56e 100644
--- a/src/math/numbertheory/reducer.cpp
+++ b/src/math/numbertheory/reducer.cpp
@@ -1,12 +1,11 @@
/*
* Modular Reducer
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/reducer.h>
-#include <botan/numthry.h>
#include <botan/internal/mp_core.h>
namespace Botan {
@@ -78,20 +77,4 @@ BigInt Modular_Reducer::reduce(const BigInt& x) const
return t1;
}
-/*
-* Multiply, followed by a reduction
-*/
-BigInt Modular_Reducer::multiply(const BigInt& x, const BigInt& y) const
- {
- return reduce(x * y);
- }
-
-/*
-* Square, followed by a reduction
-*/
-BigInt Modular_Reducer::square(const BigInt& x) const
- {
- return reduce(Botan::square(x));
- }
-
}
diff --git a/src/math/numbertheory/reducer.h b/src/math/numbertheory/reducer.h
index d234e0735..80c0f27e1 100644
--- a/src/math/numbertheory/reducer.h
+++ b/src/math/numbertheory/reducer.h
@@ -1,14 +1,14 @@
/*
* Modular Reducer
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_MODARITH_H__
-#define BOTAN_MODARITH_H__
+#ifndef BOTAN_MODULAR_REDUCER_H__
+#define BOTAN_MODULAR_REDUCER_H__
-#include <botan/bigint.h>
+#include <botan/numthry.h>
namespace Botan {
@@ -18,14 +18,30 @@ namespace Botan {
class BOTAN_DLL Modular_Reducer
{
public:
- BigInt multiply(const BigInt&, const BigInt&) const;
- BigInt square(const BigInt&) const;
- BigInt reduce(const BigInt&) const;
+ BigInt reduce(const BigInt& x) const;
+
+ /**
+ * Multiply mod p
+ */
+ BigInt multiply(const BigInt& x, const BigInt& y) const
+ { return reduce(x * y); }
+
+ /**
+ * Square mod p
+ */
+ BigInt square(const BigInt& x) const
+ { return reduce(Botan::square(x)); }
+
+ /**
+ * Cube mod p
+ */
+ BigInt cube(const BigInt& x) const
+ { return multiply(x, this->square(x)); }
bool initialized() const { return (mod_words != 0); }
Modular_Reducer() { mod_words = 0; }
- Modular_Reducer(const BigInt&);
+ Modular_Reducer(const BigInt& mod);
private:
BigInt modulus, modulus_2, mu;
u32bit mod_words, mod2_words, mu_words;