Botan 3.5.0
Crypto and TLS for C&
ec_point.h
Go to the documentation of this file.
1/*
2* Point arithmetic on elliptic curves over GF(p)
3*
4* (C) 2007 Martin Doering, Christoph Ludwig, Falko Strenzke
5* 2008-2011,2014,2015 Jack Lloyd
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#ifndef BOTAN_EC_POINT_H_
11#define BOTAN_EC_POINT_H_
12
13#include <botan/curve_gfp.h>
14#include <botan/exceptn.h>
15#include <vector>
16
17namespace Botan {
18
19enum class EC_Point_Format {
20 Uncompressed = 0,
21 Compressed = 1,
22
23 UNCOMPRESSED BOTAN_DEPRECATED("Use EC_Point_Format::Uncompressed") = Uncompressed,
24 COMPRESSED BOTAN_DEPRECATED("Use EC_Point_Format::Compressed") = Compressed,
25
26 Hybrid BOTAN_DEPRECATED("Hybrid point encoding is deprecated") = 2,
27 HYBRID BOTAN_DEPRECATED("Hybrid point encoding is deprecated") = 2
28};
29
30/**
31* This class represents one point on a curve of GF(p)
32*/
34 public:
38
40 using enum EC_Point_Format;
41
42 enum { WORKSPACE_SIZE = 8 };
43
44 /**
45 * Construct an uninitialized EC_Point
46 */
47 EC_Point() = default;
48
49 /**
50 * Construct the zero point
51 * @param curve The base curve
52 */
53 explicit EC_Point(const CurveGFp& curve);
54
55 /**
56 * Copy constructor
57 */
58 EC_Point(const EC_Point&) = default;
59
60 /**
61 * Move Constructor
62 */
63 EC_Point(EC_Point&& other) { this->swap(other); }
64
65 /**
66 * Standard Assignment
67 */
68 EC_Point& operator=(const EC_Point&) = default;
69
70 /**
71 * Move Assignment
72 */
74 if(this != &other) {
75 this->swap(other);
76 }
77 return (*this);
78 }
79
80 /**
81 * Point multiplication operator
82 *
83 * Simple unblinded Montgomery ladder
84 *
85 * Warning: prefer the functions on EC_Group such as
86 * blinded_var_point_multiply
87 *
88 * @param scalar the scalar value
89 * @return *this multiplied by the scalar value
90 */
91 EC_Point mul(const BigInt& scalar) const;
92
93 /**
94 * Construct a point from its affine coordinates
95 * Prefer EC_Group::point(x,y) for this operation.
96 * @param curve the base curve
97 * @param x affine x coordinate
98 * @param y affine y coordinate
99 */
100 EC_Point(const CurveGFp& curve, const BigInt& x, const BigInt& y);
101
102 /**
103 * EC2OSP - elliptic curve to octet string primitive
104 * @param format which format to encode using
105 */
106 std::vector<uint8_t> encode(EC_Point_Format format) const;
107
108 /**
109 * += Operator
110 * @param rhs the EC_Point to add to the local value
111 * @result resulting EC_Point
112 */
113 EC_Point& operator+=(const EC_Point& rhs);
114
115 /**
116 * -= Operator
117 * @param rhs the EC_Point to subtract from the local value
118 * @result resulting EC_Point
119 */
120 EC_Point& operator-=(const EC_Point& rhs);
121
122 /**
123 * *= Operator
124 * @param scalar the EC_Point to multiply with *this
125 * @result resulting EC_Point
126 */
127 EC_Point& operator*=(const BigInt& scalar);
128
129 /**
130 * Negate this point
131 * @return *this
132 */
134 if(!is_zero()) {
135 m_coord_y = m_curve.get_p() - m_coord_y;
136 }
137 return *this;
138 }
139
140 /**
141 * Force this point to affine coordinates
142 */
143 void force_affine();
144
145 /**
146 * Force all points on the list to affine coordinates
147 */
148 static void force_all_affine(std::span<EC_Point> points, secure_vector<word>& ws);
149
150 bool is_affine() const;
151
152 /**
153 * Is this the point at infinity?
154 * @result true, if this point is at infinity, false otherwise.
155 */
156 bool is_zero() const { return m_coord_z.is_zero(); }
157
158 /**
159 * Checks whether the point is to be found on the underlying
160 * curve; used to prevent fault attacks.
161 * @return if the point is on the curve
162 */
163 bool on_the_curve() const;
164
165 /**
166 * Return the fixed length big endian encoding of x coordinate
167 */
168 secure_vector<uint8_t> x_bytes() const;
169
170 /**
171 * Return the fixed length big endian encoding of y coordinate
172 */
173 secure_vector<uint8_t> y_bytes() const;
174
175 /**
176 * Return the fixed length concatenation of the x and y coordinates
177 */
178 secure_vector<uint8_t> xy_bytes() const;
179
180 /**
181 * get affine x coordinate
182 * @result affine x coordinate
183 */
184 BigInt get_affine_x() const;
185
186 /**
187 * get affine y coordinate
188 * @result affine y coordinate
189 */
190 BigInt get_affine_y() const;
191
192 /**
193 * Return the zero (aka infinite) point associated with this curve
194 */
195 EC_Point zero() const { return EC_Point(m_curve); }
196
197 /**
198 * Randomize the point representation
199 * The actual value (get_affine_x, get_affine_y) does not change
200 */
201 void randomize_repr(RandomNumberGenerator& rng);
202
203 /**
204 * Equality operator
205 */
206 bool operator==(const EC_Point& other) const;
207
208 bool operator!=(const EC_Point& other) const = default;
209
210 /**
211 * swaps the states of *this and other
212 * @param other the object to swap values with
213 */
214 void swap(EC_Point& other) noexcept;
215
216#if defined(BOTAN_DISABLE_DEPRECATED_FEATURES)
217
218 private:
219#endif
220
221 /**
222 * Return the internal x coordinate
223 *
224 * Note this may be in Montgomery form
225 */
226 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_x() const { return m_coord_x; }
227
228 /**
229 * Return the internal y coordinate
230 *
231 * Note this may be in Montgomery form
232 */
233 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_y() const { return m_coord_y; }
234
235 /**
236 * Return the internal z coordinate
237 *
238 * Note this may be in Montgomery form
239 */
240 BOTAN_DEPRECATED("Use affine coordinates only") const BigInt& get_z() const { return m_coord_z; }
241
242 BOTAN_DEPRECATED("Deprecated no replacement")
243
244 void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z) {
245 m_coord_x.swap(new_x);
246 m_coord_y.swap(new_y);
247 m_coord_z.swap(new_z);
248 }
249
250 friend void swap(EC_Point& x, EC_Point& y) { x.swap(y); }
251
252 /**
253 * Randomize the point representation
254 * The actual value (get_affine_x, get_affine_y) does not change
255 */
256 void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws);
257
258 /**
259 * Point addition
260 * @param other the point to add to *this
261 * @param workspace temp space, at least WORKSPACE_SIZE elements
262 */
263 void add(const EC_Point& other, std::vector<BigInt>& workspace) {
264 BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves");
265
266 const size_t p_words = m_curve.get_p_words();
267
268 add(other.m_coord_x._data(),
269 std::min(p_words, other.m_coord_x.size()),
270 other.m_coord_y._data(),
271 std::min(p_words, other.m_coord_y.size()),
272 other.m_coord_z._data(),
273 std::min(p_words, other.m_coord_z.size()),
274 workspace);
275 }
276
277 /**
278 * Point addition. Array version.
279 *
280 * @param x_words the words of the x coordinate of the other point
281 * @param x_size size of x_words
282 * @param y_words the words of the y coordinate of the other point
283 * @param y_size size of y_words
284 * @param z_words the words of the z coordinate of the other point
285 * @param z_size size of z_words
286 * @param workspace temp space, at least WORKSPACE_SIZE elements
287 */
288 void add(const word x_words[],
289 size_t x_size,
290 const word y_words[],
291 size_t y_size,
292 const word z_words[],
293 size_t z_size,
294 std::vector<BigInt>& workspace);
295
296 /**
297 * Point addition - mixed J+A
298 * @param other affine point to add - assumed to be affine!
299 * @param workspace temp space, at least WORKSPACE_SIZE elements
300 */
301 void add_affine(const EC_Point& other, std::vector<BigInt>& workspace) {
302 BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
304
305 const size_t p_words = m_curve.get_p_words();
306 add_affine(other.m_coord_x._data(),
307 std::min(p_words, other.m_coord_x.size()),
308 other.m_coord_y._data(),
309 std::min(p_words, other.m_coord_y.size()),
310 workspace);
311 }
312
313 /**
314 * Point addition - mixed J+A. Array version.
315 *
316 * @param x_words the words of the x coordinate of the other point
317 * @param x_size size of x_words
318 * @param y_words the words of the y coordinate of the other point
319 * @param y_size size of y_words
320 * @param workspace temp space, at least WORKSPACE_SIZE elements
321 */
322 void add_affine(
323 const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector<BigInt>& workspace);
324
325 /**
326 * Point doubling
327 * @param workspace temp space, at least WORKSPACE_SIZE elements
328 */
329 void mult2(std::vector<BigInt>& workspace);
330
331 /**
332 * Repeated point doubling
333 * @param i number of doublings to perform
334 * @param workspace temp space, at least WORKSPACE_SIZE elements
335 */
336 void mult2i(size_t i, std::vector<BigInt>& workspace);
337
338 /**
339 * Point addition
340 * @param other the point to add to *this
341 * @param workspace temp space, at least WORKSPACE_SIZE elements
342 * @return other plus *this
343 */
344 EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const {
345 EC_Point x = (*this);
346 x.add(other, workspace);
347 return x;
348 }
349
350 /**
351 * Point doubling
352 * @param workspace temp space, at least WORKSPACE_SIZE elements
353 * @return *this doubled
354 */
355 EC_Point double_of(std::vector<BigInt>& workspace) const {
356 EC_Point x = (*this);
357 x.mult2(workspace);
358 return x;
359 }
360
361 /**
362 * Return base curve of this point
363 * @result the curve over GF(p) of this point
364 *
365 * You should not need to use this
366 */
367 const CurveGFp& get_curve() const { return m_curve; }
368
369 private:
370 CurveGFp m_curve;
371 BigInt m_coord_x, m_coord_y, m_coord_z;
372};
373
374/**
375* ECC point multiexponentiation - not constant time!
376* @param p1 a point
377* @param z1 a scalar
378* @param p2 a point
379* @param z2 a scalar
380* @result (p1 * z1 + p2 * z2)
381*/
383EC_Point multi_exponentiate(const EC_Point& p1, const BigInt& z1, const EC_Point& p2, const BigInt& z2);
384
385// arithmetic operators
386inline EC_Point operator-(const EC_Point& lhs) {
387 return EC_Point(lhs).negate();
388}
389
390inline EC_Point operator+(const EC_Point& lhs, const EC_Point& rhs) {
391 EC_Point tmp(lhs);
392 return tmp += rhs;
393}
394
395inline EC_Point operator-(const EC_Point& lhs, const EC_Point& rhs) {
396 EC_Point tmp(lhs);
397 return tmp -= rhs;
398}
399
400inline EC_Point operator*(const EC_Point& point, const BigInt& scalar) {
401 return point.mul(scalar);
402}
403
404inline EC_Point operator*(const BigInt& scalar, const EC_Point& point) {
405 return point.mul(scalar);
406}
407
408/**
409* Perform point decoding
410* Use EC_Group::OS2ECP instead
411*/
412BOTAN_DEPRECATED("Use EC_Group::OS2ECP")
413EC_Point BOTAN_PUBLIC_API(2, 0) OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp& curve);
414
415/**
416* Perform point decoding
417* Use EC_Group::OS2ECP instead
418*
419* @param data the encoded point
420* @param data_len length of data in bytes
421* @param curve_p the curve equation prime
422* @param curve_a the curve equation a parameter
423* @param curve_b the curve equation b parameter
424*/
425BOTAN_DEPRECATED("Use EC_Group::OS2ECP")
426std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API
427 OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b);
428
429BOTAN_DEPRECATED("Use EC_Group::OS2ECP")
430EC_Point BOTAN_UNSTABLE_API OS2ECP(std::span<const uint8_t> data, const CurveGFp& curve);
431
432// The name used for this type in older versions
434
435} // namespace Botan
436
437#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
void swap(BigInt &other)
Definition bigint.h:191
size_t size() const
Definition bigint.h:609
const word * _data() const
Definition bigint.h:931
EC_Point & negate()
Definition ec_point.h:133
void swap(EC_Point &other) noexcept
Definition ec_point.cpp:568
bool operator!=(const EC_Point &other) const =default
EC_Point & operator=(EC_Point &&other)
Definition ec_point.h:73
EC_Point plus(const EC_Point &other, std::vector< BigInt > &workspace) const
Definition ec_point.h:344
void add(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:263
EC_Point(EC_Point &&other)
Definition ec_point.h:63
void add_affine(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:301
void mult2(std::vector< BigInt > &workspace)
Definition ec_point.cpp:257
EC_Point double_of(std::vector< BigInt > &workspace) const
Definition ec_point.h:355
bool is_zero() const
Definition ec_point.h:156
EC_Point zero() const
Definition ec_point.h:195
bool is_affine() const
Definition ec_point.cpp:464
EC_Point mul(const BigInt &scalar) const
Definition ec_point.cpp:364
EC_Point(const EC_Point &)=default
const CurveGFp & get_curve() const
Definition ec_point.h:367
EC_Point & operator=(const EC_Point &)=default
friend void swap(EC_Point &x, EC_Point &y)
Definition ec_point.h:250
EC_Point()=default
EC_Point_Format Compression_Type
Definition ec_point.h:39
int(* final)(unsigned char *, CTX *)
#define BOTAN_PUBLIC_API(maj, min)
Definition compiler.h:31
#define BOTAN_UNSTABLE_API
Definition compiler.h:44
#define BOTAN_DEPRECATED(msg)
Definition compiler.h:125
BigInt operator*(const BigInt &x, const BigInt &y)
Definition big_ops3.cpp:46
OctetString operator+(const OctetString &k1, const OctetString &k2)
Definition symkey.cpp:99
EC_Point multi_exponentiate(const EC_Point &p1, const BigInt &z1, const EC_Point &p2, const BigInt &z2)
Definition point_mul.cpp:24
BigInt operator-(const BigInt &x, const BigInt &y)
Definition bigint.h:1089
EC_Point_Format
Definition ec_point.h:19
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition alg_id.cpp:54
EC_Point OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
Definition ec_point.cpp:648
std::vector< T, Alloc > & operator+=(std::vector< T, Alloc > &out, const std::vector< T, Alloc2 > &in)
Definition secmem.h:80
constexpr auto operator-=(Strong< T1, Tags... > &a, T2 b)
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr auto operator*=(Strong< T1, Tags... > &a, T2 b)