Botan 3.10.0
Crypto and TLS for C&
Botan::EC_Point Class Referencefinal

#include <ec_point.h>

Public Types

enum  : uint8_t { WORKSPACE_SIZE = 8 }
typedef EC_Point_Format Compression_Type

Public Member Functions

bool _is_x_eq_to_v_mod_order (const BigInt &v) const
void add (const EC_Point &other, std::vector< BigInt > &workspace)
void add (const word x_words[], size_t x_size, const word y_words[], size_t y_size, const word z_words[], size_t z_size, std::vector< BigInt > &workspace)
void add_affine (const EC_Point &other, std::vector< BigInt > &workspace)
void add_affine (const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector< BigInt > &workspace)
EC_Point double_of (std::vector< BigInt > &workspace) const
 EC_Point ()=default
 EC_Point (const CurveGFp &curve)
 EC_Point (const CurveGFp &curve, BigInt x, BigInt y)
 EC_Point (const EC_Point &)=default
 EC_Point (EC_Point &&other) noexcept
std::vector< uint8_t > encode (EC_Point_Format format) const
void force_affine ()
BigInt get_affine_x () const
BigInt get_affine_y () const
const CurveGFpget_curve () const
const BigIntget_x () const
const BigIntget_y () const
const BigIntget_z () const
bool is_affine () const
bool is_zero () const
EC_Point mul (const BigInt &scalar) const
void mult2 (std::vector< BigInt > &workspace)
void mult2i (size_t i, std::vector< BigInt > &workspace)
EC_Pointnegate ()
bool on_the_curve () const
bool operator!= (const EC_Point &other) const =default
EC_Pointoperator*= (const BigInt &scalar)
EC_Pointoperator+= (const EC_Point &rhs)
EC_Pointoperator-= (const EC_Point &rhs)
EC_Pointoperator= (const EC_Point &)=default
EC_Pointoperator= (EC_Point &&other) noexcept
bool operator== (const EC_Point &other) const
EC_Point plus (const EC_Point &other, std::vector< BigInt > &workspace) const
void randomize_repr (RandomNumberGenerator &rng)
void randomize_repr (RandomNumberGenerator &rng, secure_vector< word > &ws)
void swap (EC_Point &other) noexcept
void swap_coords (BigInt &new_x, BigInt &new_y, BigInt &new_z)
secure_vector< uint8_t > x_bytes () const
secure_vector< uint8_t > xy_bytes () const
secure_vector< uint8_t > y_bytes () const
EC_Point zero () const
 ~EC_Point ()=default

Static Public Member Functions

static void force_all_affine (std::span< EC_Point > points, secure_vector< word > &ws)

Friends

class EC_Point_Base_Point_Precompute
class EC_Point_Multi_Point_Precompute
class EC_Point_Var_Point_Precompute
void swap (EC_Point &x, EC_Point &y) noexcept

Detailed Description

Deprecated elliptic curve type

Use EC_AffinePoint in new code; this type is no longer used internally at all except to support very unfortunate (and deprecated) curve types, specifically those with a cofactor, or with unreasonable sizes (above 521 bits), which cannot be accommodated by the new faster EC library in math/pcurves. For normal curves EC_AffinePoint will typically be 2 or 3 times faster.

This type will be completely removed in Botan4

Definition at line 33 of file ec_point.h.

Member Typedef Documentation

◆ Compression_Type

Definition at line 39 of file ec_point.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum : uint8_t
Enumerator
WORKSPACE_SIZE 

Definition at line 42 of file ec_point.h.

42: uint8_t /* NOLINT(*-use-enum-class) */ { WORKSPACE_SIZE = 8 };

Constructor & Destructor Documentation

◆ EC_Point() [1/5]

◆ EC_Point() [2/5]

Botan::EC_Point::EC_Point ( const CurveGFp & curve)
explicit

Construct the zero point

Parameters
curveThe base curve

Definition at line 107 of file ec_point.cpp.

107: m_curve(curve), m_x(0), m_y(curve.group().monty().R1()), m_z(0) {}

References EC_Point().

◆ EC_Point() [3/5]

Botan::EC_Point::EC_Point ( const EC_Point & )
default

Copy constructor

References EC_Point().

◆ EC_Point() [4/5]

Botan::EC_Point::EC_Point ( EC_Point && other)
inlinenoexcept

Move Constructor

Definition at line 63 of file ec_point.h.

63{ this->swap(other); }
void swap(EC_Point &other) noexcept
Definition ec_point.cpp:780

References EC_Point(), and swap().

◆ ~EC_Point()

Botan::EC_Point::~EC_Point ( )
default

References EC_Point(), encode(), and mul().

◆ EC_Point() [5/5]

Botan::EC_Point::EC_Point ( const CurveGFp & curve,
BigInt x,
BigInt y )

Construct a point from its affine coordinates

Parameters
curvethe base curve
xaffine x coordinate
yaffine y coordinate

Definition at line 113 of file ec_point.cpp.

113 :
114 m_curve(curve), m_x(std::move(x)), m_y(std::move(y)), m_z(m_curve.group().monty().R1()) {
115 const auto& group = m_curve.group();
116
117 if(m_x < 0 || m_x >= group.p()) {
118 throw Invalid_Argument("Invalid EC_Point affine x");
119 }
120 if(m_y < 0 || m_y >= group.p()) {
121 throw Invalid_Argument("Invalid EC_Point affine y");
122 }
123
124 secure_vector<word> monty_ws(monty_ws_size(group));
125
126 to_rep(group, m_x, monty_ws);
127 to_rep(group, m_y, monty_ws);
128}
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69

Member Function Documentation

◆ _is_x_eq_to_v_mod_order()

bool Botan::EC_Point::_is_x_eq_to_v_mod_order ( const BigInt & v) const

For internal use only

Definition at line 713 of file ec_point.cpp.

713 {
714 if(this->is_zero()) {
715 return false;
716 }
717
718 const auto& group = m_curve.group();
719
720 /*
721 * The trick used below doesn't work for curves with cofactors
722 */
723 if(group.has_cofactor()) {
724 return group.mod_order().reduce(this->get_affine_x()) == v;
725 }
726
727 /*
728 * Note we're working with the projective coordinate directly here!
729 * Nominally we're comparing v with the affine x coordinate.
730 *
731 * return group.mod_order(this->get_affine_x()) == v;
732 *
733 * However by instead projecting r to an identical z as the x
734 * coordinate, we can compare without having to perform an
735 * expensive inversion in the field.
736 *
737 * That is, given (x*z2) and r, instead of checking if
738 * (x*z2)*z2^-1 == r,
739 * we check if
740 * (x*z2) == (r*z2)
741 */
743 BigInt vr = v;
744 to_rep(group, vr, ws);
745 BigInt z2;
746 BigInt v_z2;
747 fe_sqr(group, z2, this->get_z(), ws);
748 fe_mul(group, v_z2, vr, z2, ws);
749
750 /*
751 * Since (typically) the group order is slightly less than the size
752 * of the field elements, its possible the signer had to reduce the
753 * r component. If they did not reduce r, then this value is correct.
754 *
755 * Due to the Hasse bound, this case occurs almost always; the
756 * probability that a reduction was actually required is
757 * approximately 1 in 2^(n/2) where n is the bit length of the curve.
758 */
759 if(this->get_x() == v_z2) {
760 return true;
761 }
762
763 if(group.order_is_less_than_p()) {
764 vr = v + group.order();
765 if(vr < group.p()) {
766 to_rep(group, vr, ws);
767 fe_mul(group, v_z2, vr, z2, ws);
768
769 if(this->get_x() == v_z2) {
770 return true;
771 }
772 }
773 }
774
775 // Reject:
776 return false;
777}
BigInt get_affine_x() const
Definition ec_point.cpp:630
bool is_zero() const
Definition ec_point.h:164
const BigInt & get_z() const
Definition ec_point.h:253
const BigInt & get_x() const
Definition ec_point.h:239

References get_affine_x(), get_x(), get_z(), and is_zero().

Referenced by operator!=().

◆ add() [1/2]

void Botan::EC_Point::add ( const EC_Point & other,
std::vector< BigInt > & workspace )

Point addition

Parameters
otherthe point to add to *this
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 265 of file ec_point.cpp.

265 {
266 BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves");
267
268 const size_t p_words = m_curve.get_p_words();
269
270 add(other.m_x._data(),
271 std::min(p_words, other.m_x.size()),
272 other.m_y._data(),
273 std::min(p_words, other.m_y.size()),
274 other.m_z._data(),
275 std::min(p_words, other.m_z.size()),
276 workspace);
277}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
void add(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.cpp:265

References Botan::BigInt::_data(), add(), BOTAN_ARG_CHECK, EC_Point(), and Botan::BigInt::size().

Referenced by add(), mul(), Botan::EC_Point_Var_Point_Precompute::mul(), Botan::EC_Point_Multi_Point_Precompute::multi_exp(), operator+=(), and plus().

◆ add() [2/2]

void Botan::EC_Point::add ( const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size,
const word z_words[],
size_t z_size,
std::vector< BigInt > & workspace )

Point addition. Array version.

Parameters
x_wordsthe words of the x coordinate of the other point
x_sizesize of x_words
y_wordsthe words of the y coordinate of the other point
y_sizesize of y_words
z_wordsthe words of the z coordinate of the other point
z_sizesize of z_words
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 279 of file ec_point.cpp.

285 {
286 if((CT::all_zeros(x_words, x_size) & CT::all_zeros(z_words, z_size)).as_bool()) {
287 return;
288 }
289
290 const auto& group = m_curve.group();
291
292 if(is_zero()) {
293 m_x.set_words(x_words, x_size);
294 m_y.set_words(y_words, y_size);
295 m_z.set_words(z_words, z_size);
296 return;
297 }
298
299 resize_ws(ws_bn, monty_ws_size(group));
300
301 secure_vector<word>& ws = ws_bn[0].get_word_vector();
302 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
303
304 BigInt& T0 = ws_bn[2];
305 BigInt& T1 = ws_bn[3];
306 BigInt& T2 = ws_bn[4];
307 BigInt& T3 = ws_bn[5];
308 BigInt& T4 = ws_bn[6];
309 BigInt& T5 = ws_bn[7];
310
311 /*
312 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
313 */
314
315 const BigInt& p = group.p();
316
317 fe_sqr(group, T0, z_words, z_size, ws); // z2^2
318 fe_mul(group, T1, m_x, T0, ws); // x1*z2^2
319 fe_mul(group, T3, z_words, z_size, T0, ws); // z2^3
320 fe_mul(group, T2, m_y, T3, ws); // y1*z2^3
321
322 fe_sqr(group, T3, m_z, ws); // z1^2
323 fe_mul(group, T4, x_words, x_size, T3, ws); // x2*z1^2
324
325 fe_mul(group, T5, m_z, T3, ws); // z1^3
326 fe_mul(group, T0, y_words, y_size, T5, ws); // y2*z1^3
327
328 T4.mod_sub(T1, p, sub_ws); // x2*z1^2 - x1*z2^2
329
330 T0.mod_sub(T2, p, sub_ws);
331
332 if(T4.is_zero()) {
333 if(T0.is_zero()) {
334 mult2(ws_bn);
335 return;
336 }
337
338 // setting to zero:
339 m_x.clear();
340 m_y = group.monty().R1();
341 m_z.clear();
342 return;
343 }
344
345 fe_sqr(group, T5, T4, ws);
346
347 fe_mul(group, T3, T1, T5, ws);
348
349 fe_mul(group, T1, T5, T4, ws);
350
351 fe_sqr(group, m_x, T0, ws);
352 m_x.mod_sub(T1, p, sub_ws);
353 m_x.mod_sub(T3, p, sub_ws);
354 m_x.mod_sub(T3, p, sub_ws);
355
356 T3.mod_sub(m_x, p, sub_ws);
357
358 fe_mul(group, m_y, T0, T3, ws);
359 fe_mul(group, T3, T2, T1, ws);
360
361 m_y.mod_sub(T3, p, sub_ws);
362
363 fe_mul(group, T3, z_words, z_size, m_z, ws);
364 fe_mul(group, m_z, T3, T4, ws);
365}
void mult2(std::vector< BigInt > &workspace)
Definition ec_point.cpp:387
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
Definition ct_utils.h:813

References Botan::CT::all_zeros(), Botan::BigInt::is_zero(), is_zero(), Botan::BigInt::mod_sub(), and mult2().

◆ add_affine() [1/2]

void Botan::EC_Point::add_affine ( const EC_Point & other,
std::vector< BigInt > & workspace )

Point addition - mixed J+A

Warning
This function assumes that other is affine, if this is not correct the result will be invalid.
Parameters
otheraffine point to add - assumed to be affine!
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 174 of file ec_point.cpp.

174 {
175 BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
176 BOTAN_DEBUG_ASSERT(other.is_affine());
177
178 const size_t p_words = m_curve.get_p_words();
179 add_affine(other.m_x._data(),
180 std::min(p_words, other.m_x.size()),
181 other.m_y._data(),
182 std::min(p_words, other.m_y.size()),
183 workspace);
184}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
void add_affine(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.cpp:174

References Botan::BigInt::_data(), add_affine(), BOTAN_ASSERT_NOMSG, BOTAN_DEBUG_ASSERT, EC_Point(), is_affine(), and Botan::BigInt::size().

Referenced by add_affine(), Botan::EC_Point_Base_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

◆ add_affine() [2/2]

void Botan::EC_Point::add_affine ( const word x_words[],
size_t x_size,
const word y_words[],
size_t y_size,
std::vector< BigInt > & workspace )

Point addition - mixed J+A. Array version.

Parameters
x_wordsthe words of the x coordinate of the other point
x_sizesize of x_words
y_wordsthe words of the y coordinate of the other point
y_sizesize of y_words
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 186 of file ec_point.cpp.

187 {
188 if((CT::all_zeros(x_words, x_size) & CT::all_zeros(y_words, y_size)).as_bool()) {
189 return;
190 }
191
192 const auto& group = m_curve.group();
193
194 if(is_zero()) {
195 m_x.set_words(x_words, x_size);
196 m_y.set_words(y_words, y_size);
197 m_z = group.monty().R1();
198 return;
199 }
200
201 resize_ws(ws_bn, monty_ws_size(group));
202
203 secure_vector<word>& ws = ws_bn[0].get_word_vector();
204 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
205
206 BigInt& T0 = ws_bn[2];
207 BigInt& T1 = ws_bn[3];
208 BigInt& T2 = ws_bn[4];
209 BigInt& T3 = ws_bn[5];
210 BigInt& T4 = ws_bn[6];
211
212 /*
213 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-1998-cmo-2
214 simplified with Z2 = 1
215 */
216
217 const BigInt& p = group.p();
218
219 fe_sqr(group, T3, m_z, ws); // z1^2
220 fe_mul(group, T4, x_words, x_size, T3, ws); // x2*z1^2
221
222 fe_mul(group, T2, m_z, T3, ws); // z1^3
223 fe_mul(group, T0, y_words, y_size, T2, ws); // y2*z1^3
224
225 T4.mod_sub(m_x, p, sub_ws); // x2*z1^2 - x1*z2^2
226
227 T0.mod_sub(m_y, p, sub_ws);
228
229 if(T4.is_zero()) {
230 if(T0.is_zero()) {
231 mult2(ws_bn);
232 return;
233 }
234
235 // setting to zero:
236 m_x.clear();
237 m_y = group.monty().R1();
238 m_z.clear();
239 return;
240 }
241
242 fe_sqr(group, T2, T4, ws);
243
244 fe_mul(group, T3, m_x, T2, ws);
245
246 fe_mul(group, T1, T2, T4, ws);
247
248 fe_sqr(group, m_x, T0, ws);
249 m_x.mod_sub(T1, p, sub_ws);
250
251 m_x.mod_sub(T3, p, sub_ws);
252 m_x.mod_sub(T3, p, sub_ws);
253
254 T3.mod_sub(m_x, p, sub_ws);
255
256 fe_mul(group, T2, T0, T3, ws);
257 fe_mul(group, T0, m_y, T1, ws);
258 T2.mod_sub(T0, p, sub_ws);
259 m_y.swap(T2);
260
261 fe_mul(group, T0, m_z, T4, ws);
262 m_z.swap(T0);
263}

References Botan::CT::all_zeros(), Botan::BigInt::is_zero(), is_zero(), Botan::BigInt::mod_sub(), mult2(), and Botan::BigInt::swap().

◆ double_of()

EC_Point Botan::EC_Point::double_of ( std::vector< BigInt > & workspace) const
inline

Point doubling

Parameters
workspacetemp space, at least WORKSPACE_SIZE elements
Returns
*this doubled

Definition at line 350 of file ec_point.h.

350 {
351 EC_Point x = (*this);
352 x.mult2(workspace);
353 return x;
354 }
EC_Point()=default

References EC_Point(), and mult2().

◆ encode()

std::vector< uint8_t > Botan::EC_Point::encode ( EC_Point_Format format) const

EC2OSP - elliptic curve to octet string primitive

Parameters
formatwhich format to encode using

Definition at line 801 of file ec_point.cpp.

801 {
802 if(is_zero()) {
803 return std::vector<uint8_t>(1); // single 0 byte
804 }
805
806 const size_t p_bytes = m_curve.group().p_bytes();
807
808 const BigInt x = get_affine_x();
809 const BigInt y = get_affine_y();
810
811 const size_t parts = (format == EC_Point_Format::Compressed) ? 1 : 2;
812
813 std::vector<uint8_t> result(1 + parts * p_bytes);
814 BufferStuffer stuffer(result);
815
816 if(format == EC_Point_Format::Uncompressed) {
817 stuffer.append(0x04);
818 x.serialize_to(stuffer.next(p_bytes));
819 y.serialize_to(stuffer.next(p_bytes));
820 } else if(format == EC_Point_Format::Compressed) {
821 stuffer.append(0x02 | static_cast<uint8_t>(y.get_bit(0)));
822 x.serialize_to(stuffer.next(p_bytes));
823 } else if(format == EC_Point_Format::Hybrid) {
824 stuffer.append(0x06 | static_cast<uint8_t>(y.get_bit(0)));
825 x.serialize_to(stuffer.next(p_bytes));
826 y.serialize_to(stuffer.next(p_bytes));
827 } else {
828 throw Invalid_Argument("EC2OSP illegal point encoding");
829 }
830
831 return result;
832}
BigInt get_affine_y() const
Definition ec_point.cpp:652

References Botan::BufferStuffer::append(), Botan::Compressed, get_affine_x(), get_affine_y(), Botan::BigInt::get_bit(), Botan::Hybrid, is_zero(), Botan::BufferStuffer::next(), Botan::BigInt::serialize_to(), and Botan::Uncompressed.

Referenced by ~EC_Point().

◆ force_affine()

void Botan::EC_Point::force_affine ( )

Force this point to affine coordinates

Convert the point to its equivalent affine coordinates. Throws if this is the point at infinity.

Definition at line 583 of file ec_point.cpp.

583 {
584 if(is_zero()) {
585 throw Invalid_State("Cannot convert zero ECC point to affine");
586 }
587
589
590 const auto& group = m_curve.group();
591
592 const BigInt z_inv = invert_element(group, m_z, ws);
593 const BigInt z2_inv = fe_sqr(group, z_inv, ws);
594 const BigInt z3_inv = fe_mul(group, z_inv, z2_inv, ws);
595 m_x = fe_mul(group, m_x, z2_inv, ws);
596 m_y = fe_mul(group, m_y, z3_inv, ws);
597 m_z = group.monty().R1();
598}

References is_zero().

◆ force_all_affine()

void Botan::EC_Point::force_all_affine ( std::span< EC_Point > points,
secure_vector< word > & ws )
static

Force all points on the list to affine coordinates

Force several points to be affine at once. Uses Montgomery's trick to reduce number of inversions required, so this is much faster than calling force_affine on each point in sequence.

Definition at line 519 of file ec_point.cpp.

519 {
520 if(points.size() <= 1) {
521 for(auto& point : points) {
522 point.force_affine();
523 }
524 return;
525 }
526
527 for(auto& point : points) {
528 if(point.is_zero()) {
529 throw Invalid_State("Cannot convert zero ECC point to affine");
530 }
531 }
532
533 /*
534 For >= 2 points use Montgomery's trick
535
536 See Algorithm 2.26 in "Guide to Elliptic Curve Cryptography"
537 (Hankerson, Menezes, Vanstone)
538
539 TODO is it really necessary to save all k points in c?
540 */
541
542 const auto& group = points[0].m_curve.group();
543 const BigInt& rep_1 = group.monty().R1();
544
545 if(ws.size() < monty_ws_size(group)) {
546 ws.resize(monty_ws_size(group));
547 }
548
549 std::vector<BigInt> c(points.size());
550 c[0] = points[0].m_z;
551
552 for(size_t i = 1; i != points.size(); ++i) {
553 fe_mul(group, c[i], c[i - 1], points[i].m_z, ws);
554 }
555
556 BigInt s_inv = invert_element(group, c[c.size() - 1], ws);
557
558 BigInt z_inv;
559 BigInt z2_inv;
560 BigInt z3_inv;
561
562 for(size_t i = points.size() - 1; i != 0; i--) {
563 EC_Point& point = points[i];
564
565 fe_mul(group, z_inv, s_inv, c[i - 1], ws);
566
567 s_inv = fe_mul(group, s_inv, point.m_z, ws);
568
569 fe_sqr(group, z2_inv, z_inv, ws);
570 fe_mul(group, z3_inv, z2_inv, z_inv, ws);
571 point.m_x = fe_mul(group, point.m_x, z2_inv, ws);
572 point.m_y = fe_mul(group, point.m_y, z3_inv, ws);
573 point.m_z = rep_1;
574 }
575
576 fe_sqr(group, z2_inv, s_inv, ws);
577 fe_mul(group, z3_inv, z2_inv, s_inv, ws);
578 points[0].m_x = fe_mul(group, points[0].m_x, z2_inv, ws);
579 points[0].m_y = fe_mul(group, points[0].m_y, z3_inv, ws);
580 points[0].m_z = rep_1;
581}

References EC_Point().

Referenced by Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), and Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute().

◆ get_affine_x()

BigInt Botan::EC_Point::get_affine_x ( ) const

get affine x coordinate

Returns
affine x coordinate

Definition at line 630 of file ec_point.cpp.

630 {
631 if(is_zero()) {
632 throw Invalid_State("Cannot convert zero point to affine");
633 }
634
635 secure_vector<word> monty_ws;
636
637 const auto& group = m_curve.group();
638
639 if(is_affine()) {
640 return from_rep_to_tmp(group, m_x, monty_ws);
641 }
642
643 BigInt z2 = fe_sqr(group, m_z, monty_ws);
644 z2 = invert_element(group, z2, monty_ws);
645
646 BigInt r;
647 fe_mul(group, r, m_x, z2, monty_ws);
648 from_rep(group, r, monty_ws);
649 return r;
650}
bool is_affine() const
Definition ec_point.cpp:600

References is_affine(), and is_zero().

Referenced by _is_x_eq_to_v_mod_order(), encode(), operator==(), and xy_bytes().

◆ get_affine_y()

BigInt Botan::EC_Point::get_affine_y ( ) const

get affine y coordinate

Returns
affine y coordinate

Definition at line 652 of file ec_point.cpp.

652 {
653 if(is_zero()) {
654 throw Invalid_State("Cannot convert zero point to affine");
655 }
656
657 const auto& group = m_curve.group();
658 secure_vector<word> monty_ws;
659
660 if(is_affine()) {
661 return from_rep_to_tmp(group, m_y, monty_ws);
662 }
663
664 const BigInt z2 = fe_sqr(group, m_z, monty_ws);
665 const BigInt z3 = fe_mul(group, m_z, z2, monty_ws);
666 const BigInt z3_inv = invert_element(group, z3, monty_ws);
667
668 BigInt r;
669 fe_mul(group, r, m_y, z3_inv, monty_ws);
670 from_rep(group, r, monty_ws);
671 return r;
672}

References is_affine(), and is_zero().

Referenced by encode(), operator==(), and xy_bytes().

◆ get_curve()

const CurveGFp & Botan::EC_Point::get_curve ( ) const
inline

Return base curve of this point

Returns
the curve over GF(p) of this point

You should not need to use this

Definition at line 362 of file ec_point.h.

362{ return m_curve; }

References get_curve().

Referenced by get_curve().

◆ get_x()

const BigInt & Botan::EC_Point::get_x ( ) const
inline

Return the internal x coordinate

Note this may be in Montgomery form

Definition at line 239 of file ec_point.h.

239{ return m_x; }

References get_x().

Referenced by _is_x_eq_to_v_mod_order(), and get_x().

◆ get_y()

const BigInt & Botan::EC_Point::get_y ( ) const
inline

Return the internal y coordinate

Note this may be in Montgomery form

Definition at line 246 of file ec_point.h.

246{ return m_y; }

References get_y().

Referenced by get_y().

◆ get_z()

const BigInt & Botan::EC_Point::get_z ( ) const
inline

Return the internal z coordinate

Note this may be in Montgomery form

Definition at line 253 of file ec_point.h.

253{ return m_z; }

References get_z().

Referenced by _is_x_eq_to_v_mod_order(), and get_z().

◆ is_affine()

bool Botan::EC_Point::is_affine ( ) const

Definition at line 600 of file ec_point.cpp.

600 {
601 const auto& group = m_curve.group();
602 return m_z == group.monty().R1();
603}

Referenced by add_affine(), get_affine_x(), and get_affine_y().

◆ is_zero()

bool Botan::EC_Point::is_zero ( ) const
inline

Is this the point at infinity?

Returns
true, if this point is at infinity, false otherwise.

Definition at line 164 of file ec_point.h.

164{ return m_z.is_zero(); }

Referenced by _is_x_eq_to_v_mod_order(), add(), add_affine(), encode(), force_affine(), get_affine_x(), get_affine_y(), mult2(), negate(), on_the_curve(), operator-=(), and operator==().

◆ mul()

EC_Point Botan::EC_Point::mul ( const BigInt & scalar) const

Point multiplication operator

Simple unblinded Montgomery ladder

Warning: prefer the functions on EC_Group such as blinded_var_point_multiply

Parameters
scalarthe scalar value
Returns
*this multiplied by the scalar value

Definition at line 496 of file ec_point.cpp.

496 {
497 const size_t scalar_bits = scalar.bits();
498
499 std::vector<BigInt> ws(EC_Point::WORKSPACE_SIZE);
500
501 EC_Point R[2] = {this->zero(), *this};
502
503 for(size_t i = scalar_bits; i > 0; i--) {
504 const size_t b = scalar.get_bit(i - 1) ? 1 : 0;
505 R[b ^ 1].add(R[b], ws);
506 R[b].mult2(ws);
507 }
508
509 if(scalar.is_negative()) {
510 R[0].negate();
511 }
512
514
515 return R[0];
516}
bool on_the_curve() const
Definition ec_point.cpp:674
EC_Point zero() const
Definition ec_point.cpp:109

References add(), Botan::BigInt::bits(), BOTAN_DEBUG_ASSERT, EC_Point(), Botan::BigInt::get_bit(), Botan::BigInt::is_negative(), mult2(), negate(), on_the_curve(), WORKSPACE_SIZE, and zero().

Referenced by Botan::operator*(), Botan::operator*(), and ~EC_Point().

◆ mult2()

void Botan::EC_Point::mult2 ( std::vector< BigInt > & workspace)

Point doubling

Parameters
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 387 of file ec_point.cpp.

387 {
388 if(is_zero()) {
389 return;
390 }
391
392 const auto& group = m_curve.group();
393
394 if(m_y.is_zero()) {
395 *this = EC_Point(m_curve); // setting myself to zero
396 return;
397 }
398
399 resize_ws(ws_bn, monty_ws_size(group));
400
401 secure_vector<word>& ws = ws_bn[0].get_word_vector();
402 secure_vector<word>& sub_ws = ws_bn[1].get_word_vector();
403
404 BigInt& T0 = ws_bn[2];
405 BigInt& T1 = ws_bn[3];
406 BigInt& T2 = ws_bn[4];
407 BigInt& T3 = ws_bn[5];
408 BigInt& T4 = ws_bn[6];
409
410 /*
411 https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc
412 */
413 const BigInt& p = group.p();
414
415 fe_sqr(group, T0, m_y, ws);
416
417 fe_mul(group, T1, m_x, T0, ws);
418 fe_smul<4>(T1, p, sub_ws);
419
420 if(group.a_is_zero()) {
421 // if a == 0 then 3*x^2 + a*z^4 is just 3*x^2
422 fe_sqr(group, T4, m_x, ws); // x^2
423 fe_smul<3>(T4, p, sub_ws); // 3*x^2
424 } else if(group.a_is_minus_3()) {
425 /*
426 if a == -3 then
427 3*x^2 + a*z^4 == 3*x^2 - 3*z^4 == 3*(x^2-z^4) == 3*(x-z^2)*(x+z^2)
428 */
429 fe_sqr(group, T3, m_z, ws); // z^2
430
431 // (x-z^2)
432 T2 = m_x;
433 T2.mod_sub(T3, p, sub_ws);
434
435 // (x+z^2)
436 T3.mod_add(m_x, p, sub_ws);
437
438 fe_mul(group, T4, T2, T3, ws); // (x-z^2)*(x+z^2)
439
440 fe_smul<3>(T4, p, sub_ws); // 3*(x-z^2)*(x+z^2)
441 } else {
442 fe_sqr(group, T3, m_z, ws); // z^2
443 fe_sqr(group, T4, T3, ws); // z^4
444 fe_mul(group, T3, group.monty_a(), T4, ws); // a*z^4
445
446 fe_sqr(group, T4, m_x, ws); // x^2
447 fe_smul<3>(T4, p, sub_ws);
448 T4.mod_add(T3, p, sub_ws); // 3*x^2 + a*z^4
449 }
450
451 fe_sqr(group, T2, T4, ws);
452 T2.mod_sub(T1, p, sub_ws);
453 T2.mod_sub(T1, p, sub_ws);
454
455 fe_sqr(group, T3, T0, ws);
456 fe_smul<8>(T3, p, sub_ws);
457
458 T1.mod_sub(T2, p, sub_ws);
459
460 fe_mul(group, T0, T4, T1, ws);
461 T0.mod_sub(T3, p, sub_ws);
462
463 m_x.swap(T2);
464
465 fe_mul(group, T2, m_y, m_z, ws);
466 fe_smul<2>(T2, p, sub_ws);
467
468 m_y.swap(T0);
469 m_z.swap(T2);
470}

References EC_Point(), is_zero(), Botan::BigInt::mod_add(), Botan::BigInt::mod_sub(), and Botan::BigInt::swap().

Referenced by add(), add_affine(), double_of(), Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), and mult2i().

◆ mult2i()

void Botan::EC_Point::mult2i ( size_t i,
std::vector< BigInt > & workspace )

Repeated point doubling

Parameters
inumber of doublings to perform
workspacetemp space, at least WORKSPACE_SIZE elements

Definition at line 367 of file ec_point.cpp.

367 {
368 if(iterations == 0) {
369 return;
370 }
371
372 if(m_y.is_zero()) {
373 *this = EC_Point(m_curve); // setting myself to zero
374 return;
375 }
376
377 /*
378 TODO we can save 2 squarings per iteration by computing
379 a*Z^4 using values cached from previous iteration
380 */
381 for(size_t i = 0; i != iterations; ++i) {
382 mult2(ws_bn);
383 }
384}

References EC_Point(), and mult2().

Referenced by Botan::EC_Point_Var_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

◆ negate()

EC_Point & Botan::EC_Point::negate ( )
inline

Negate this point

Returns
*this

Definition at line 134 of file ec_point.h.

134 {
135 if(!is_zero()) {
136 m_y = m_curve.get_p() - m_y;
137 }
138 return *this;
139 }

References EC_Point(), is_zero(), and negate().

Referenced by mul(), Botan::EC_Point_Multi_Point_Precompute::multi_exp(), negate(), and Botan::operator-().

◆ on_the_curve()

bool Botan::EC_Point::on_the_curve ( ) const

Checks whether the point is to be found on the underlying curve; used to prevent fault attacks.

Returns
if the point is on the curve

Definition at line 674 of file ec_point.cpp.

674 {
675 /*
676 Is the point still on the curve?? (If everything is correct, the
677 point is always on its curve; then the function will return true.
678 If somehow the state is corrupted, which suggests a fault attack
679 (or internal computational error), then return false.
680 */
681 if(is_zero()) {
682 return true;
683 }
684
685 const auto& group = m_curve.group();
686 secure_vector<word> monty_ws;
687
688 const BigInt y2 = from_rep_to_tmp(group, fe_sqr(group, m_y, monty_ws), monty_ws);
689 const BigInt x3 = fe_mul(group, m_x, fe_sqr(group, m_x, monty_ws), monty_ws);
690 const BigInt ax = fe_mul(group, m_x, group.monty_a(), monty_ws);
691 const BigInt z2 = fe_sqr(group, m_z, monty_ws);
692
693 const BigInt& monty_b = group.monty_b();
694
695 // Is z equal to 1 (in Montgomery form)?
696 if(m_z == z2) {
697 if(y2 != from_rep_to_tmp(group, x3 + ax + monty_b, monty_ws)) {
698 return false;
699 }
700 }
701
702 const BigInt z3 = fe_mul(group, m_z, z2, monty_ws);
703 const BigInt ax_z4 = fe_mul(group, ax, fe_sqr(group, z2, monty_ws), monty_ws);
704 const BigInt b_z6 = fe_mul(group, monty_b, fe_sqr(group, z3, monty_ws), monty_ws);
705
706 if(y2 != from_rep_to_tmp(group, x3 + ax_z4 + b_z6, monty_ws)) {
707 return false;
708 }
709
710 return true;
711}

References is_zero().

Referenced by Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), Botan::EC_Point_Base_Point_Precompute::mul(), Botan::EC_Point_Var_Point_Precompute::mul(), Botan::OS2ECP(), and Botan::EC_Group::verify_group().

◆ operator!=()

bool Botan::EC_Point::operator!= ( const EC_Point & other) const
default

◆ operator*=()

EC_Point & Botan::EC_Point::operator*= ( const BigInt & scalar)

*= Operator

Parameters
scalarthe EC_Point to multiply with *this
Returns
resulting EC_Point

Definition at line 491 of file ec_point.cpp.

491 {
492 *this = scalar * *this;
493 return *this;
494}

References EC_Point().

◆ operator+=()

EC_Point & Botan::EC_Point::operator+= ( const EC_Point & rhs)

+= Operator

Parameters
rhsthe EC_Point to add to the local value
Returns
resulting EC_Point

Definition at line 473 of file ec_point.cpp.

473 {
474 std::vector<BigInt> ws(EC_Point::WORKSPACE_SIZE);
475 add(rhs, ws);
476 return *this;
477}

References add(), EC_Point(), and WORKSPACE_SIZE.

◆ operator-=()

EC_Point & Botan::EC_Point::operator-= ( const EC_Point & rhs)

-= Operator

Parameters
rhsthe EC_Point to subtract from the local value
Returns
resulting EC_Point

Definition at line 479 of file ec_point.cpp.

479 {
480 EC_Point minus_rhs = EC_Point(rhs).negate();
481
482 if(is_zero()) {
483 *this = minus_rhs;
484 } else {
485 *this += minus_rhs;
486 }
487
488 return *this;
489}

References EC_Point(), and is_zero().

◆ operator=() [1/2]

EC_Point & Botan::EC_Point::operator= ( const EC_Point & )
default

Standard Assignment

References EC_Point().

◆ operator=() [2/2]

EC_Point & Botan::EC_Point::operator= ( EC_Point && other)
inlinenoexcept

Move Assignment

Definition at line 73 of file ec_point.h.

73 {
74 if(this != &other) {
75 this->swap(other);
76 }
77 return (*this);
78 }

References EC_Point(), and swap().

◆ operator==()

bool Botan::EC_Point::operator== ( const EC_Point & other) const

Equality operator

Definition at line 787 of file ec_point.cpp.

787 {
788 if(m_curve != other.m_curve) {
789 return false;
790 }
791
792 // If this is zero, only equal if other is also zero
793 if(is_zero()) {
794 return other.is_zero();
795 }
796
797 return (get_affine_x() == other.get_affine_x() && get_affine_y() == other.get_affine_y());
798}

References EC_Point(), get_affine_x(), get_affine_y(), and is_zero().

◆ plus()

EC_Point Botan::EC_Point::plus ( const EC_Point & other,
std::vector< BigInt > & workspace ) const
inline

Point addition

Parameters
otherthe point to add to *this
workspacetemp space, at least WORKSPACE_SIZE elements
Returns
other plus *this

Definition at line 339 of file ec_point.h.

339 {
340 EC_Point x = (*this);
341 x.add(other, workspace);
342 return x;
343 }

References add(), and EC_Point().

Referenced by Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), and Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute().

◆ randomize_repr() [1/2]

void Botan::EC_Point::randomize_repr ( RandomNumberGenerator & rng)

Randomize the point representation The actual value (get_affine_x, get_affine_y) does not change

Definition at line 130 of file ec_point.cpp.

130 {
131 const auto& group = m_curve.group();
132 secure_vector<word> ws(monty_ws_size(group));
133 randomize_repr(rng, ws);
134}
void randomize_repr(RandomNumberGenerator &rng)
Definition ec_point.cpp:130

References randomize_repr().

Referenced by Botan::EC_Point_Var_Point_Precompute::EC_Point_Var_Point_Precompute(), Botan::EC_Point_Base_Point_Precompute::mul(), Botan::EC_Point_Var_Point_Precompute::mul(), and randomize_repr().

◆ randomize_repr() [2/2]

void Botan::EC_Point::randomize_repr ( RandomNumberGenerator & rng,
secure_vector< word > & ws )

Randomize the point representation The actual value (get_affine_x, get_affine_y) does not change

Definition at line 136 of file ec_point.cpp.

136 {
137 if(!rng.is_seeded()) {
138 return;
139 }
140
141 const auto& group = m_curve.group();
142
143 const BigInt mask = BigInt::random_integer(rng, BigInt::from_s32(2), group.p());
144
145 /*
146 * No reason to convert this to Montgomery representation first,
147 * just pretend the random mask was chosen as Redc(mask) and the
148 * random mask we generated above is in the Montgomery
149 * representation.
150 */
151
152 const BigInt mask2 = fe_sqr(group, mask, ws);
153 const BigInt mask3 = fe_mul(group, mask2, mask, ws);
154
155 m_x = fe_mul(group, m_x, mask2, ws);
156 m_y = fe_mul(group, m_y, mask3, ws);
157 m_z = fe_mul(group, m_z, mask, ws);
158}
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition big_rand.cpp:43
static BigInt from_s32(int32_t n)
Definition bigint.cpp:41

References Botan::BigInt::from_s32(), Botan::RandomNumberGenerator::is_seeded(), and Botan::BigInt::random_integer().

◆ swap()

void Botan::EC_Point::swap ( EC_Point & other)
noexcept

swaps the states of *this and other

Parameters
otherthe object to swap values with

Definition at line 780 of file ec_point.cpp.

780 {
781 m_curve.swap(other.m_curve);
782 m_x.swap(other.m_x);
783 m_y.swap(other.m_y);
784 m_z.swap(other.m_z);
785}

References EC_Point().

Referenced by EC_Point(), Botan::EC_Point_Base_Point_Precompute::EC_Point_Base_Point_Precompute(), operator!=(), and operator=().

◆ swap_coords()

void Botan::EC_Point::swap_coords ( BigInt & new_x,
BigInt & new_y,
BigInt & new_z )
inline

Definition at line 257 of file ec_point.h.

257 {
258 m_x.swap(new_x);
259 m_y.swap(new_y);
260 m_z.swap(new_z);
261 }

References swap_coords().

Referenced by swap_coords().

◆ x_bytes()

secure_vector< uint8_t > Botan::EC_Point::x_bytes ( ) const

Return the fixed length big endian encoding of x coordinate

Definition at line 605 of file ec_point.cpp.

605 {
606 const auto& group = m_curve.group();
607 const size_t p_bytes = group.p_bytes();
608 secure_vector<uint8_t> b(p_bytes);
609 BigInt::encode_1363(b.data(), b.size(), this->get_affine_x());
610 return b;
611}
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition bigint.h:895

References Botan::BigInt::encode_1363().

◆ xy_bytes()

secure_vector< uint8_t > Botan::EC_Point::xy_bytes ( ) const

Return the fixed length concatenation of the x and y coordinates

Definition at line 621 of file ec_point.cpp.

621 {
622 const auto& group = m_curve.group();
623 const size_t p_bytes = group.p_bytes();
624 secure_vector<uint8_t> b(2 * p_bytes);
625 BigInt::encode_1363(&b[0], p_bytes, this->get_affine_x()); // NOLINT(*container-data-pointer)
626 BigInt::encode_1363(&b[p_bytes], p_bytes, this->get_affine_y());
627 return b;
628}

References Botan::BigInt::encode_1363(), get_affine_x(), and get_affine_y().

◆ y_bytes()

secure_vector< uint8_t > Botan::EC_Point::y_bytes ( ) const

Return the fixed length big endian encoding of y coordinate

Definition at line 613 of file ec_point.cpp.

613 {
614 const auto& group = m_curve.group();
615 const size_t p_bytes = group.p_bytes();
616 secure_vector<uint8_t> b(p_bytes);
617 BigInt::encode_1363(b.data(), b.size(), this->get_affine_y());
618 return b;
619}

References Botan::BigInt::encode_1363().

◆ zero()

EC_Point Botan::EC_Point::zero ( ) const

Return the zero (aka infinite) point associated with this curve

Definition at line 109 of file ec_point.cpp.

109 {
110 return EC_Point(m_curve);
111}

References EC_Point().

Referenced by Botan::EC_Point_Multi_Point_Precompute::EC_Point_Multi_Point_Precompute(), mul(), Botan::EC_Point_Base_Point_Precompute::mul(), and Botan::EC_Point_Multi_Point_Precompute::multi_exp().

◆ EC_Point_Base_Point_Precompute

friend class EC_Point_Base_Point_Precompute
friend

Definition at line 37 of file ec_point.h.

References EC_Point_Base_Point_Precompute.

Referenced by EC_Point_Base_Point_Precompute.

◆ EC_Point_Multi_Point_Precompute

friend class EC_Point_Multi_Point_Precompute
friend

Definition at line 36 of file ec_point.h.

References EC_Point_Multi_Point_Precompute.

Referenced by EC_Point_Multi_Point_Precompute.

◆ EC_Point_Var_Point_Precompute

friend class EC_Point_Var_Point_Precompute
friend

Definition at line 35 of file ec_point.h.

References EC_Point_Var_Point_Precompute.

Referenced by EC_Point_Var_Point_Precompute.

◆ swap

void swap ( EC_Point & x,
EC_Point & y )
friend

Definition at line 263 of file ec_point.h.

263{ x.swap(y); }

References EC_Point().


The documentation for this class was generated from the following files: