Coverage Report

Created: 2025-07-11 06:15

/src/Botan-3.4.0/build/include/public/botan/ec_point.h
Line
Count
Source (jump to first uncovered line)
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
17
namespace Botan {
18
19
enum 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
*/
33
class BOTAN_PUBLIC_API(2, 0) EC_Point final {
34
   public:
35
      typedef EC_Point_Format Compression_Type;
36
      using enum EC_Point_Format;
37
38
      enum { WORKSPACE_SIZE = 8 };
39
40
      /**
41
      * Construct an uninitialized EC_Point
42
      */
43
29.8k
      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
1.24M
      EC_Point(const EC_Point&) = default;
55
56
      /**
57
      * Move Constructor
58
      */
59
548k
      EC_Point(EC_Point&& other) { this->swap(other); }
60
61
      /**
62
      * Standard Assignment
63
      */
64
17.0k
      EC_Point& operator=(const EC_Point&) = default;
65
66
      /**
67
      * Move Assignment
68
      */
69
21.3k
      EC_Point& operator=(EC_Point&& other) {
70
21.3k
         if(this != &other) {
71
21.3k
            this->swap(other);
72
21.3k
         }
73
21.3k
         return (*this);
74
21.3k
      }
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
      */
116
0
      EC_Point& negate() {
117
0
         if(!is_zero()) {
118
0
            m_coord_y = m_curve.get_p() - m_coord_y;
119
0
         }
120
0
         return *this;
121
0
      }
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
29.8k
      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
29.8k
      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
0
      const BigInt& get_z() const { return m_coord_z; }
155
156
0
      void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z) {
157
0
         m_coord_x.swap(new_x);
158
0
         m_coord_y.swap(new_y);
159
0
         m_coord_z.swap(new_z);
160
0
      }
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
30.2M
      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
0
      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
681k
      void add(const EC_Point& other, std::vector<BigInt>& workspace) {
218
681k
         BOTAN_ARG_CHECK(m_curve == other.m_curve, "cannot add points on different curves");
219
220
681k
         const size_t p_words = m_curve.get_p_words();
221
222
681k
         add(other.m_coord_x.data(),
223
681k
             std::min(p_words, other.m_coord_x.size()),
224
681k
             other.m_coord_y.data(),
225
681k
             std::min(p_words, other.m_coord_y.size()),
226
681k
             other.m_coord_z.data(),
227
681k
             std::min(p_words, other.m_coord_z.size()),
228
681k
             workspace);
229
681k
      }
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
8.77M
      void add_affine(const EC_Point& other, std::vector<BigInt>& workspace) {
256
8.77M
         BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
257
8.77M
         BOTAN_DEBUG_ASSERT(other.is_affine());
258
259
8.77M
         const size_t p_words = m_curve.get_p_words();
260
8.77M
         add_affine(other.m_coord_x.data(),
261
8.77M
                    std::min(p_words, other.m_coord_x.size()),
262
8.77M
                    other.m_coord_y.data(),
263
8.77M
                    std::min(p_words, other.m_coord_y.size()),
264
8.77M
                    workspace);
265
8.77M
      }
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
681k
      EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const {
299
681k
         EC_Point x = (*this);
300
681k
         x.add(other, workspace);
301
681k
         return x;
302
681k
      }
303
304
      /**
305
      * Point doubling
306
      * @param workspace temp space, at least WORKSPACE_SIZE elements
307
      * @return *this doubled
308
      */
309
0
      EC_Point double_of(std::vector<BigInt>& workspace) const {
310
0
         EC_Point x = (*this);
311
0
         x.mult2(workspace);
312
0
         return x;
313
0
      }
314
315
      /**
316
      * Return the zero (aka infinite) point associated with this curve
317
      */
318
59.7k
      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
48
      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
*/
339
BOTAN_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
*/
349
BOTAN_PUBLIC_API(2, 0)
350
EC_Point multi_exponentiate(const EC_Point& p1, const BigInt& z1, const EC_Point& p2, const BigInt& z2);
351
352
// relational operators
353
0
inline bool operator!=(const EC_Point& lhs, const EC_Point& rhs) {
354
0
   return !(rhs == lhs);
355
0
}
356
357
// arithmetic operators
358
0
inline EC_Point operator-(const EC_Point& lhs) {
359
0
   return EC_Point(lhs).negate();
360
0
}
361
362
0
inline EC_Point operator+(const EC_Point& lhs, const EC_Point& rhs) {
363
0
   EC_Point tmp(lhs);
364
0
   return tmp += rhs;
365
0
}
366
367
0
inline EC_Point operator-(const EC_Point& lhs, const EC_Point& rhs) {
368
0
   EC_Point tmp(lhs);
369
0
   return tmp -= rhs;
370
0
}
371
372
0
inline EC_Point operator*(const EC_Point& point, const BigInt& scalar) {
373
0
   return scalar * point;
374
0
}
375
376
/**
377
* Perform point decoding
378
* Use EC_Group::OS2ECP instead
379
*/
380
EC_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
*/
392
std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API
393
OS2ECP(const uint8_t data[], size_t data_len, const BigInt& curve_p, const BigInt& curve_a, const BigInt& curve_b);
394
395
template <typename Alloc>
396
EC_Point OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve) {
397
   return OS2ECP(data.data(), data.size(), curve);
398
}
399
400
class EC_Point_Var_Point_Precompute;
401
402
// The name used for this type in older versions
403
typedef EC_Point PointGFp;
404
405
}  // namespace Botan
406
407
#endif