aboutsummaryrefslogtreecommitdiffstats
path: root/src/math/ec_gfp/point_gfp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/math/ec_gfp/point_gfp.cpp')
-rw-r--r--src/math/ec_gfp/point_gfp.cpp606
1 files changed, 0 insertions, 606 deletions
diff --git a/src/math/ec_gfp/point_gfp.cpp b/src/math/ec_gfp/point_gfp.cpp
deleted file mode 100644
index 9cd5a2aaf..000000000
--- a/src/math/ec_gfp/point_gfp.cpp
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
-* Point arithmetic on elliptic curves over GF(p)
-*
-* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
-* 2008-2011,2012 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/point_gfp.h>
-#include <botan/numthry.h>
-#include <botan/reducer.h>
-#include <botan/internal/mp_core.h>
-
-namespace Botan {
-
-PointGFp::PointGFp(const CurveGFp& curve) :
- curve(curve), ws(2 * (curve.get_p_words() + 2))
- {
- coord_x = 0;
- coord_y = monty_mult(1, curve.get_r2());
- coord_z = 0;
- }
-
-PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) :
- curve(curve), ws(2 * (curve.get_p_words() + 2))
- {
- coord_x = monty_mult(x, curve.get_r2());
- coord_y = monty_mult(y, curve.get_r2());
- coord_z = monty_mult(1, curve.get_r2());
- }
-
-// Montgomery multiplication
-void PointGFp::monty_mult(BigInt& z, const BigInt& x, const BigInt& y) const
- {
- //assert(&z != &x && &z != &y);
-
- if(x.is_zero() || y.is_zero())
- {
- z = 0;
- return;
- }
-
- const BigInt& p = curve.get_p();
- const size_t p_size = curve.get_p_words();
- const word p_dash = curve.get_p_dash();
-
- const size_t output_size = 2*p_size + 1;
-
- z.grow_to(output_size);
- z.clear();
-
- bigint_monty_mul(z.mutable_data(), output_size,
- x.data(), x.size(), x.sig_words(),
- y.data(), y.size(), y.sig_words(),
- p.data(), p_size, p_dash,
- &ws[0]);
- }
-
-// Montgomery squaring
-void PointGFp::monty_sqr(BigInt& z, const BigInt& x) const
- {
- //assert(&z != &x);
-
- if(x.is_zero())
- {
- z = 0;
- return;
- }
-
- const BigInt& p = curve.get_p();
- const size_t p_size = curve.get_p_words();
- const word p_dash = curve.get_p_dash();
-
- const size_t output_size = 2*p_size + 1;
-
- z.grow_to(output_size);
- z.clear();
-
- bigint_monty_sqr(z.mutable_data(), output_size,
- x.data(), x.size(), x.sig_words(),
- p.data(), p_size, p_dash,
- &ws[0]);
- }
-
-// Point addition
-void PointGFp::add(const PointGFp& rhs, std::vector<BigInt>& ws_bn)
- {
- if(is_zero())
- {
- coord_x = rhs.coord_x;
- coord_y = rhs.coord_y;
- coord_z = rhs.coord_z;
- return;
- }
- else if(rhs.is_zero())
- return;
-
- const BigInt& p = curve.get_p();
-
- BigInt& rhs_z2 = ws_bn[0];
- BigInt& U1 = ws_bn[1];
- BigInt& S1 = ws_bn[2];
-
- BigInt& lhs_z2 = ws_bn[3];
- BigInt& U2 = ws_bn[4];
- BigInt& S2 = ws_bn[5];
-
- BigInt& H = ws_bn[6];
- BigInt& r = ws_bn[7];
-
- monty_sqr(rhs_z2, rhs.coord_z);
- monty_mult(U1, coord_x, rhs_z2);
- monty_mult(S1, coord_y, monty_mult(rhs.coord_z, rhs_z2));
-
- monty_sqr(lhs_z2, coord_z);
- monty_mult(U2, rhs.coord_x, lhs_z2);
- monty_mult(S2, rhs.coord_y, monty_mult(coord_z, lhs_z2));
-
- H = U2;
- H -= U1;
- if(H.is_negative())
- H += p;
-
- r = S2;
- r -= S1;
- if(r.is_negative())
- r += p;
-
- if(H.is_zero())
- {
- if(r.is_zero())
- {
- mult2(ws_bn);
- return;
- }
-
- *this = PointGFp(curve); // setting myself to zero
- return;
- }
-
- monty_sqr(U2, H);
-
- monty_mult(S2, U2, H);
-
- U2 = monty_mult(U1, U2);
-
- monty_sqr(coord_x, r);
- coord_x -= S2;
- coord_x -= (U2 << 1);
- while(coord_x.is_negative())
- coord_x += p;
-
- U2 -= coord_x;
- if(U2.is_negative())
- U2 += p;
-
- monty_mult(coord_y, r, U2);
- coord_y -= monty_mult(S1, S2);
- if(coord_y.is_negative())
- coord_y += p;
-
- monty_mult(coord_z, monty_mult(coord_z, rhs.coord_z), H);
- }
-
-// *this *= 2
-void PointGFp::mult2(std::vector<BigInt>& ws_bn)
- {
- if(is_zero())
- return;
- else if(coord_y.is_zero())
- {
- *this = PointGFp(curve); // setting myself to zero
- return;
- }
-
- const BigInt& p = curve.get_p();
-
- BigInt& y_2 = ws_bn[0];
- BigInt& S = ws_bn[1];
- BigInt& z4 = ws_bn[2];
- BigInt& a_z4 = ws_bn[3];
- BigInt& M = ws_bn[4];
- BigInt& U = ws_bn[5];
- BigInt& x = ws_bn[6];
- BigInt& y = ws_bn[7];
- BigInt& z = ws_bn[8];
-
- monty_sqr(y_2, coord_y);
-
- monty_mult(S, coord_x, y_2);
- S <<= 2; // * 4
- while(S >= p)
- S -= p;
-
- monty_sqr(z4, monty_sqr(coord_z));
- monty_mult(a_z4, curve.get_a_r(), z4);
-
- M = 3 * monty_sqr(coord_x);
- M += a_z4;
- while(M >= p)
- M -= p;
-
- monty_sqr(x, M);
- x -= (S << 1);
- while(x.is_negative())
- x += p;
-
- monty_sqr(U, y_2);
- U <<= 3;
- while(U >= p)
- U -= p;
-
- S -= x;
- while(S.is_negative())
- S += p;
-
- monty_mult(y, M, S);
- y -= U;
- if(y.is_negative())
- y += p;
-
- monty_mult(z, coord_y, coord_z);
- z <<= 1;
- if(z >= p)
- z -= p;
-
- coord_x = x;
- coord_y = y;
- coord_z = z;
- }
-
-// arithmetic operators
-PointGFp& PointGFp::operator+=(const PointGFp& rhs)
- {
- std::vector<BigInt> ws(9);
- add(rhs, ws);
- 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)
- {
- *this = scalar * *this;
- return *this;
- }
-
-PointGFp multi_exponentiate(const PointGFp& p1, const BigInt& z1,
- const PointGFp& p2, const BigInt& z2)
- {
- const PointGFp p3 = p1 + p2;
-
- PointGFp H(p1.curve); // create as zero
- size_t bits_left = std::max(z1.bits(), z2.bits());
-
- std::vector<BigInt> ws(9);
-
- while(bits_left)
- {
- H.mult2(ws);
-
- const bool z1_b = z1.get_bit(bits_left - 1);
- const bool z2_b = z2.get_bit(bits_left - 1);
-
- if(z1_b == true && z2_b == true)
- H.add(p3, ws);
- else if(z1_b)
- H.add(p1, ws);
- else if(z2_b)
- H.add(p2, ws);
-
- --bits_left;
- }
-
- if(z1.is_negative() != z2.is_negative())
- H.negate();
-
- return H;
- }
-
-PointGFp operator*(const BigInt& scalar, const PointGFp& point)
- {
- const CurveGFp& curve = point.get_curve();
-
- if(scalar.is_zero())
- return PointGFp(curve); // zero point
-
- std::vector<BigInt> ws(9);
-
- if(scalar.abs() <= 2) // special cases for small values
- {
- byte value = scalar.abs().byte_at(0);
-
- PointGFp result = point;
-
- if(value == 2)
- result.mult2(ws);
-
- if(scalar.is_negative())
- result.negate();
-
- return result;
- }
-
- const size_t scalar_bits = scalar.bits();
-
-#if 0
-
- PointGFp x1 = PointGFp(curve);
- PointGFp x2 = point;
-
- size_t bits_left = scalar_bits;
-
- // Montgomery Ladder
- while(bits_left)
- {
- const bool bit_set = scalar.get_bit(bits_left - 1);
-
- if(bit_set)
- {
- x1.add(x2, ws);
- x2.mult2(ws);
- }
- else
- {
- x2.add(x1, ws);
- x1.mult2(ws);
- }
-
- --bits_left;
- }
-
- if(scalar.is_negative())
- x1.negate();
-
- return x1;
-
-#else
- const size_t window_size = 4;
-
- std::vector<PointGFp> Ps(1 << window_size);
- Ps[0] = PointGFp(curve);
- Ps[1] = point;
-
- for(size_t i = 2; i != Ps.size(); ++i)
- {
- Ps[i] = Ps[i-1];
- Ps[i].add(point, ws);
- }
-
- PointGFp H(curve); // create as zero
- size_t bits_left = scalar_bits;
-
- while(bits_left >= window_size)
- {
- for(size_t i = 0; i != window_size; ++i)
- H.mult2(ws);
-
- const u32bit nibble = scalar.get_substring(bits_left - window_size,
- window_size);
-
- H.add(Ps[nibble], ws);
-
- bits_left -= window_size;
- }
-
- while(bits_left)
- {
- H.mult2(ws);
- if(scalar.get_bit(bits_left-1))
- H.add(point, ws);
-
- --bits_left;
- }
-
- if(scalar.is_negative())
- H.negate();
-
- return H;
-#endif
- }
-
-BigInt PointGFp::get_affine_x() const
- {
- if(is_zero())
- throw Illegal_Transformation("Cannot convert zero point to affine");
-
- const BigInt& r2 = curve.get_r2();
-
- BigInt z2 = monty_sqr(coord_z);
- z2 = inverse_mod(z2, curve.get_p());
-
- z2 = monty_mult(z2, r2);
- return monty_mult(coord_x, z2);
- }
-
-BigInt PointGFp::get_affine_y() const
- {
- if(is_zero())
- throw Illegal_Transformation("Cannot convert zero point to affine");
-
- const BigInt& r2 = curve.get_r2();
-
- BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z));
- z3 = inverse_mod(z3, curve.get_p());
- z3 = monty_mult(z3, r2);
- return monty_mult(coord_y, z3);
- }
-
-bool PointGFp::on_the_curve() const
- {
- /*
- Is the point still on the curve?? (If everything is correct, the
- point is always on its curve; then the function will return true.
- If somehow the state is corrupted, which suggests a fault attack
- (or internal computational error), then return false.
- */
-
- if(is_zero())
- return true;
-
- BigInt y2 = monty_mult(monty_sqr(coord_y), 1);
- BigInt x3 = monty_mult(coord_x, monty_sqr(coord_x));
-
- BigInt ax = monty_mult(coord_x, curve.get_a_r());
-
- const BigInt& b_r = curve.get_b_r();
-
- BigInt z2 = monty_sqr(coord_z);
-
- if(coord_z == z2) // Is z equal to 1 (in Montgomery form)?
- {
- if(y2 != monty_mult(x3 + ax + b_r, 1))
- return false;
- }
-
- BigInt z3 = monty_mult(coord_z, z2);
-
- BigInt ax_z4 = monty_mult(ax, monty_sqr(z2));
-
- BigInt b_z6 = monty_mult(b_r, monty_sqr(z3));
-
- if(y2 != monty_mult(x3 + ax_z4 + b_z6, 1))
- return false;
-
- return true;
- }
-
-// 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);
- ws.swap(other.ws);
- }
-
-bool PointGFp::operator==(const PointGFp& other) const
- {
- if(get_curve() != other.get_curve())
- return false;
-
- // If this is zero, only equal if other is also zero
- if(is_zero())
- return other.is_zero();
-
- return (get_affine_x() == other.get_affine_x() &&
- get_affine_y() == other.get_affine_y());
- }
-
-// encoding and decoding
-secure_vector<byte> EC2OSP(const PointGFp& point, byte format)
- {
- if(point.is_zero())
- return secure_vector<byte>(1); // single 0 byte
-
- const size_t p_bytes = point.get_curve().get_p().bytes();
-
- BigInt x = point.get_affine_x();
- BigInt y = point.get_affine_y();
-
- secure_vector<byte> bX = BigInt::encode_1363(x, p_bytes);
- secure_vector<byte> bY = BigInt::encode_1363(y, p_bytes);
-
- if(format == PointGFp::UNCOMPRESSED)
- {
- secure_vector<byte> result;
- result.push_back(0x04);
-
- result += bX;
- result += bY;
-
- return result;
- }
- else if(format == PointGFp::COMPRESSED)
- {
- secure_vector<byte> result;
- result.push_back(0x02 | static_cast<byte>(y.get_bit(0)));
-
- result += bX;
-
- return result;
- }
- else if(format == PointGFp::HYBRID)
- {
- secure_vector<byte> result;
- result.push_back(0x06 | static_cast<byte>(y.get_bit(0)));
-
- result += bX;
- result += bY;
-
- return result;
- }
- else
- throw Invalid_Argument("illegal point encoding format specification");
- }
-
-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;
- }
-
-}
-
-PointGFp OS2ECP(const byte data[], size_t data_len,
- const CurveGFp& curve)
- {
- if(data_len <= 1)
- return PointGFp(curve); // return zero
-
- const byte pc = data[0];
-
- BigInt x, y;
-
- if(pc == 2 || pc == 3)
- {
- //compressed form
- x = BigInt::decode(&data[1], data_len - 1);
-
- const bool y_mod_2 = ((pc & 0x01) == 1);
- y = decompress_point(y_mod_2, x, curve);
- }
- else if(pc == 4)
- {
- const size_t l = (data_len - 1) / 2;
-
- // uncompressed form
- x = BigInt::decode(&data[1], l);
- y = BigInt::decode(&data[l+1], l);
- }
- else if(pc == 6 || pc == 7)
- {
- const size_t l = (data_len - 1) / 2;
-
- // hybrid form
- x = BigInt::decode(&data[1], l);
- y = BigInt::decode(&data[l+1], l);
-
- const bool y_mod_2 = ((pc & 0x01) == 1);
-
- if(decompress_point(y_mod_2, x, curve) != y)
- throw Illegal_Point("OS2ECP: Decoding error in hybrid format");
- }
- else
- throw Invalid_Argument("OS2ECP: Unknown format type " + std::to_string(pc));
-
- PointGFp result(curve, x, y);
-
- if(!result.on_the_curve())
- throw Illegal_Point("OS2ECP: Decoded point was not on the curve");
-
- return result;
- }
-
-}