Botan 3.4.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:
36 using enum EC_Point_Format;
37
38 enum { WORKSPACE_SIZE = 8 };
39
40 /**
41 * Construct an uninitialized EC_Point
42 */
43 EC_Point() = default;
44
45 /**
46 * Construct the zero point
47 * @param curve The base curve
48 */
49 explicit EC_Point(const CurveGFp& curve);
50
51 /**
52 * Copy constructor
53 */
54 EC_Point(const EC_Point&) = default;
55
56 /**
57 * Move Constructor
58 */
59 EC_Point(EC_Point&& other) { this->swap(other); }
60
61 /**
62 * Standard Assignment
63 */
64 EC_Point& operator=(const EC_Point&) = default;
65
66 /**
67 * Move Assignment
68 */
70 if(this != &other) {
71 this->swap(other);
72 }
73 return (*this);
74 }
75
76 /**
77 * Construct a point from its affine coordinates
78 * Prefer EC_Group::point(x,y) for this operation.
79 * @param curve the base curve
80 * @param x affine x coordinate
81 * @param y affine y coordinate
82 */
83 EC_Point(const CurveGFp& curve, const BigInt& x, const BigInt& y);
84
85 /**
86 * EC2OSP - elliptic curve to octet string primitive
87 * @param format which format to encode using
88 */
89 std::vector<uint8_t> encode(EC_Point_Format format) const;
90
91 /**
92 * += Operator
93 * @param rhs the EC_Point to add to the local value
94 * @result resulting EC_Point
95 */
96 EC_Point& operator+=(const EC_Point& rhs);
97
98 /**
99 * -= Operator
100 * @param rhs the EC_Point to subtract from the local value
101 * @result resulting EC_Point
102 */
103 EC_Point& operator-=(const EC_Point& rhs);
104
105 /**
106 * *= Operator
107 * @param scalar the EC_Point to multiply with *this
108 * @result resulting EC_Point
109 */
110 EC_Point& operator*=(const BigInt& scalar);
111
112 /**
113 * Negate this point
114 * @return *this
115 */
117 if(!is_zero()) {
118 m_coord_y = m_curve.get_p() - m_coord_y;
119 }
120 return *this;
121 }
122
123 /**
124 * get affine x coordinate
125 * @result affine x coordinate
126 */
127 BigInt get_affine_x() const;
128
129 /**
130 * get affine y coordinate
131 * @result affine y coordinate
132 */
133 BigInt get_affine_y() const;
134
135 /**
136 * Return the internal x coordinate
137 *
138 * Note this may be in Montgomery form
139 */
140 const BigInt& get_x() const { return m_coord_x; }
141
142 /**
143 * Return the internal y coordinate
144 *
145 * Note this may be in Montgomery form
146 */
147 const BigInt& get_y() const { return m_coord_y; }
148
149 /**
150 * Return the internal z coordinate
151 *
152 * Note this may be in Montgomery form
153 */
154 const BigInt& get_z() const { return m_coord_z; }
155
156 void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z) {
157 m_coord_x.swap(new_x);
158 m_coord_y.swap(new_y);
159 m_coord_z.swap(new_z);
160 }
161
162 /**
163 * Force this point to affine coordinates
164 */
165 void force_affine();
166
167 /**
168 * Force all points on the list to affine coordinates
169 */
170 static void force_all_affine(std::vector<EC_Point>& points, secure_vector<word>& ws);
171
172 bool is_affine() const;
173
174 /**
175 * Is this the point at infinity?
176 * @result true, if this point is at infinity, false otherwise.
177 */
178 bool is_zero() const { return m_coord_z.is_zero(); }
179
180 /**
181 * Checks whether the point is to be found on the underlying
182 * curve; used to prevent fault attacks.
183 * @return if the point is on the curve
184 */
185 bool on_the_curve() const;
186
187 /**
188 * swaps the states of *this and other, does not throw!
189 * @param other the object to swap values with
190 */
191 void swap(EC_Point& other);
192
193 friend void swap(EC_Point& x, EC_Point& y) { x.swap(y); }
194
195 /**
196 * Randomize the point representation
197 * The actual value (get_affine_x, get_affine_y) does not change
198 */
199 void randomize_repr(RandomNumberGenerator& rng);
200
201 /**
202 * Randomize the point representation
203 * The actual value (get_affine_x, get_affine_y) does not change
204 */
205 void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws);
206
207 /**
208 * Equality operator
209 */
210 bool operator==(const EC_Point& other) const;
211
212 /**
213 * Point addition
214 * @param other the point to add to *this
215 * @param workspace temp space, at least WORKSPACE_SIZE elements
216 */
217 void add(const EC_Point& other, std::vector<BigInt>& workspace) {
218 BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves");
219
220 const size_t p_words = m_curve.get_p_words();
221
222 add(other.m_coord_x.data(),
223 std::min(p_words, other.m_coord_x.size()),
224 other.m_coord_y.data(),
225 std::min(p_words, other.m_coord_y.size()),
226 other.m_coord_z.data(),
227 std::min(p_words, other.m_coord_z.size()),
228 workspace);
229 }
230
231 /**
232 * Point addition. Array version.
233 *
234 * @param x_words the words of the x coordinate of the other point
235 * @param x_size size of x_words
236 * @param y_words the words of the y coordinate of the other point
237 * @param y_size size of y_words
238 * @param z_words the words of the z coordinate of the other point
239 * @param z_size size of z_words
240 * @param workspace temp space, at least WORKSPACE_SIZE elements
241 */
242 void add(const word x_words[],
243 size_t x_size,
244 const word y_words[],
245 size_t y_size,
246 const word z_words[],
247 size_t z_size,
248 std::vector<BigInt>& workspace);
249
250 /**
251 * Point addition - mixed J+A
252 * @param other affine point to add - assumed to be affine!
253 * @param workspace temp space, at least WORKSPACE_SIZE elements
254 */
255 void add_affine(const EC_Point& other, std::vector<BigInt>& workspace) {
256 BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
258
259 const size_t p_words = m_curve.get_p_words();
260 add_affine(other.m_coord_x.data(),
261 std::min(p_words, other.m_coord_x.size()),
262 other.m_coord_y.data(),
263 std::min(p_words, other.m_coord_y.size()),
264 workspace);
265 }
266
267 /**
268 * Point addition - mixed J+A. Array version.
269 *
270 * @param x_words the words of the x coordinate of the other point
271 * @param x_size size of x_words
272 * @param y_words the words of the y coordinate of the other point
273 * @param y_size size of y_words
274 * @param workspace temp space, at least WORKSPACE_SIZE elements
275 */
276 void add_affine(
277 const word x_words[], size_t x_size, const word y_words[], size_t y_size, std::vector<BigInt>& workspace);
278
279 /**
280 * Point doubling
281 * @param workspace temp space, at least WORKSPACE_SIZE elements
282 */
283 void mult2(std::vector<BigInt>& workspace);
284
285 /**
286 * Repeated point doubling
287 * @param i number of doublings to perform
288 * @param workspace temp space, at least WORKSPACE_SIZE elements
289 */
290 void mult2i(size_t i, std::vector<BigInt>& workspace);
291
292 /**
293 * Point addition
294 * @param other the point to add to *this
295 * @param workspace temp space, at least WORKSPACE_SIZE elements
296 * @return other plus *this
297 */
298 EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const {
299 EC_Point x = (*this);
300 x.add(other, workspace);
301 return x;
302 }
303
304 /**
305 * Point doubling
306 * @param workspace temp space, at least WORKSPACE_SIZE elements
307 * @return *this doubled
308 */
309 EC_Point double_of(std::vector<BigInt>& workspace) const {
310 EC_Point x = (*this);
311 x.mult2(workspace);
312 return x;
313 }
314
315 /**
316 * Return the zero (aka infinite) point associated with this curve
317 */
318 EC_Point zero() const { return EC_Point(m_curve); }
319
320 /**
321 * Return base curve of this point
322 * @result the curve over GF(p) of this point
323 *
324 * You should not need to use this
325 */
326 const CurveGFp& get_curve() const { return m_curve; }
327
328 private:
329 CurveGFp m_curve;
330 BigInt m_coord_x, m_coord_y, m_coord_z;
331};
332
333/**
334* Point multiplication operator
335* @param scalar the scalar value
336* @param point the point value
337* @return scalar*point on the curve
338*/
339BOTAN_PUBLIC_API(2, 0) EC_Point operator*(const BigInt& scalar, const EC_Point& point);
340
341/**
342* ECC point multiexponentiation - not constant time!
343* @param p1 a point
344* @param z1 a scalar
345* @param p2 a point
346* @param z2 a scalar
347* @result (p1 * z1 + p2 * z2)
348*/
350EC_Point multi_exponentiate(const EC_Point& p1, const BigInt& z1, const EC_Point& p2, const BigInt& z2);
351
352// relational operators
353inline bool operator!=(const EC_Point& lhs, const EC_Point& rhs) {
354 return !(rhs == lhs);
355}
356
357// arithmetic operators
358inline EC_Point operator-(const EC_Point& lhs) {
359 return EC_Point(lhs).negate();
360}
361
362inline EC_Point operator+(const EC_Point& lhs, const EC_Point& rhs) {
363 EC_Point tmp(lhs);
364 return tmp += rhs;
365}
366
367inline EC_Point operator-(const EC_Point& lhs, const EC_Point& rhs) {
368 EC_Point tmp(lhs);
369 return tmp -= rhs;
370}
371
372inline EC_Point operator*(const EC_Point& point, const BigInt& scalar) {
373 return scalar * point;
374}
375
376/**
377* Perform point decoding
378* Use EC_Group::OS2ECP instead
379*/
380EC_Point BOTAN_PUBLIC_API(2, 0) OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp& curve);
381
382/**
383* Perform point decoding
384* Use EC_Group::OS2ECP instead
385*
386* @param data the encoded point
387* @param data_len length of data in bytes
388* @param curve_p the curve equation prime
389* @param curve_a the curve equation a parameter
390* @param curve_b the curve equation b parameter
391*/
392std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API
393OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b);
394
395template <typename Alloc>
396EC_Point OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve) {
397 return OS2ECP(data.data(), data.size(), curve);
398}
399
400class EC_Point_Var_Point_Precompute;
401
402// The name used for this type in older versions
404
405} // namespace Botan
406
407#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
size_t size() const
Definition bigint.h:578
const word * data() const
Definition bigint.h:615
EC_Point & negate()
Definition ec_point.h:116
EC_Point & operator=(EC_Point &&other)
Definition ec_point.h:69
EC_Point plus(const EC_Point &other, std::vector< BigInt > &workspace) const
Definition ec_point.h:298
void swap(EC_Point &other)
Definition ec_point.cpp:547
void add(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:217
EC_Point(EC_Point &&other)
Definition ec_point.h:59
void add_affine(const EC_Point &other, std::vector< BigInt > &workspace)
Definition ec_point.h:255
void mult2(std::vector< BigInt > &workspace)
Definition ec_point.cpp:256
EC_Point double_of(std::vector< BigInt > &workspace) const
Definition ec_point.h:309
const BigInt & get_y() const
Definition ec_point.h:147
bool is_zero() const
Definition ec_point.h:178
const BigInt & get_z() const
Definition ec_point.h:154
void swap_coords(BigInt &new_x, BigInt &new_y, BigInt &new_z)
Definition ec_point.h:156
EC_Point zero() const
Definition ec_point.h:318
bool is_affine() const
Definition ec_point.cpp:465
EC_Point(const EC_Point &)=default
const CurveGFp & get_curve() const
Definition ec_point.h:326
EC_Point & operator=(const EC_Point &)=default
friend void swap(EC_Point &x, EC_Point &y)
Definition ec_point.h:193
const BigInt & get_x() const
Definition ec_point.h:140
EC_Point()=default
EC_Point_Format Compression_Type
Definition ec_point.h:35
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
EC_Point PointGFp
Definition ec_point.h:403
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:963
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:627
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)