Coverage Report

Created: 2025-07-16 06:16

/src/botan/build/include/public/botan/ec_apoint.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2024 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef BOTAN_EC_APOINT_H_
8
#define BOTAN_EC_APOINT_H_
9
10
#include <botan/concepts.h>
11
#include <botan/ec_point_format.h>
12
#include <botan/secmem.h>
13
#include <botan/types.h>
14
#include <memory>
15
#include <optional>
16
#include <span>
17
#include <string_view>
18
#include <vector>
19
20
namespace Botan {
21
22
class BigInt;
23
class RandomNumberGenerator;
24
class EC_Group;
25
class EC_Scalar;
26
27
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
28
class EC_Point;
29
#endif
30
31
class EC_Group_Data;
32
class EC_AffinePoint_Data;
33
34
/// Elliptic Curve Point in Affine Representation
35
///
36
class BOTAN_PUBLIC_API(3, 6) EC_AffinePoint final {
37
   public:
38
      /// Point deserialization. Throws if wrong length or not a valid point
39
      ///
40
      /// This accepts SEC1 compressed or uncompressed formats
41
      EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes);
42
43
      /// Point deserialization. Returns nullopt if wrong length or not a valid point
44
      ///
45
      /// This accepts SEC1 compressed or uncompressed formats
46
      static std::optional<EC_AffinePoint> deserialize(const EC_Group& group, std::span<const uint8_t> bytes);
47
48
      /// Create a point from a pair (x,y) of integers
49
      ///
50
      /// The integers must be within the field - in the range [0,p) and must
51
      /// satisfy the curve equation
52
      static std::optional<EC_AffinePoint> from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y);
53
54
      /// Multiply by the group generator returning a complete point
55
      static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng);
56
57
      /// Return the identity element
58
      static EC_AffinePoint identity(const EC_Group& group);
59
60
      /// Return the standard group generator
61
      static EC_AffinePoint generator(const EC_Group& group);
62
63
      /// Hash to curve (RFC 9380), random oracle variant
64
      ///
65
      /// Only supported for specific groups
66
      static EC_AffinePoint hash_to_curve_ro(const EC_Group& group,
67
                                             std::string_view hash_fn,
68
                                             std::span<const uint8_t> input,
69
                                             std::span<const uint8_t> domain_sep);
70
71
      /// Hash to curve (RFC 9380), random oracle variant
72
      ///
73
      /// Only supported for specific groups
74
      static EC_AffinePoint hash_to_curve_ro(const EC_Group& group,
75
                                             std::string_view hash_fn,
76
                                             std::span<const uint8_t> input,
77
                                             std::string_view domain_sep);
78
79
      /// Hash to curve (RFC 9380), non uniform variant
80
      ///
81
      /// Only supported for specific groups
82
      static EC_AffinePoint hash_to_curve_nu(const EC_Group& group,
83
                                             std::string_view hash_fn,
84
                                             std::span<const uint8_t> input,
85
                                             std::span<const uint8_t> domain_sep);
86
87
      /// Hash to curve (RFC 9380), non uniform variant
88
      ///
89
      /// Only supported for specific groups
90
      static EC_AffinePoint hash_to_curve_nu(const EC_Group& group,
91
                                             std::string_view hash_fn,
92
                                             std::span<const uint8_t> input,
93
                                             std::string_view domain_sep);
94
95
      /// Multiply a point by a scalar returning a complete point
96
      EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;
97
98
      /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only
99
      secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;
100
101
      /// Compute 2-ary multiscalar multiplication - p*x + q*y
102
      ///
103
      /// This operation runs in constant time with respect to p, x, q, and y
104
      ///
105
      /// @returns p*x+q*y, or nullopt if the result was the point at infinity
106
      static std::optional<EC_AffinePoint> mul_px_qy(const EC_AffinePoint& p,
107
                                                     const EC_Scalar& x,
108
                                                     const EC_AffinePoint& q,
109
                                                     const EC_Scalar& y,
110
                                                     RandomNumberGenerator& rng);
111
112
      /// Point addition
113
      ///
114
      /// Note that this is quite slow since it converts the resulting
115
      /// projective point immediately to affine coordinates, which requires a
116
      /// field inversion. This can be sufficient when implementing protocols
117
      /// that just need to perform a few additions.
118
      ///
119
      /// In the future a cooresponding EC_ProjectivePoint type may be added
120
      /// which would avoid the expensive affine conversions
121
      EC_AffinePoint add(const EC_AffinePoint& q) const;
122
123
      /// Point negation
124
      EC_AffinePoint negate() const;
125
126
      /// Return the number of bytes of a field element
127
      ///
128
      /// A point consists of two field elements, plus possibly a header
129
      size_t field_element_bytes() const;
130
131
      /// Return true if this point is the identity element
132
      bool is_identity() const;
133
134
      /// Write the fixed length encoding of affine x coordinate
135
      ///
136
      /// The output span must be exactly field_element_bytes long
137
      ///
138
      /// This function will fail if this point is the identity element
139
      void serialize_x_to(std::span<uint8_t> bytes) const;
140
141
      /// Write the fixed length encoding of affine y coordinate
142
      ///
143
      /// The output span must be exactly field_element_bytes long
144
      ///
145
      /// This function will fail if this point is the identity element
146
      void serialize_y_to(std::span<uint8_t> bytes) const;
147
148
      /// Write the fixed length encoding of affine x and y coordinates
149
      ///
150
      /// The output span must be exactly 2*field_element_bytes long
151
      ///
152
      /// This function will fail if this point is the identity element
153
      void serialize_xy_to(std::span<uint8_t> bytes) const;
154
155
      /// Write the fixed length SEC1 compressed encoding
156
      ///
157
      /// The output span must be exactly 1 + field_element_bytes long
158
      ///
159
      /// This function will fail if this point is the identity element
160
      void serialize_compressed_to(std::span<uint8_t> bytes) const;
161
162
      /// Return the fixed length encoding of SEC1 uncompressed encoding
163
      ///
164
      /// The output span must be exactly 1 + 2*field_element_bytes long
165
      ///
166
      /// This function will fail if this point is the identity element
167
      void serialize_uncompressed_to(std::span<uint8_t> bytes) const;
168
169
      /// Return the bytes of the affine x coordinate in a container
170
      ///
171
      /// This function will fail if this point is the identity element
172
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
173
0
      T x_bytes() const {
174
0
         T bytes(this->field_element_bytes());
175
0
         this->serialize_x_to(bytes);
176
0
         return bytes;
177
0
      }
178
179
      /// Return the bytes of the affine y coordinate in a container
180
      ///
181
      /// This function will fail if this point is the identity element
182
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
183
0
      T y_bytes() const {
184
0
         T bytes(this->field_element_bytes());
185
0
         this->serialize_y_to(bytes);
186
0
         return bytes;
187
0
      }
188
189
      /// Return the bytes of the affine x and y coordinates in a container
190
      ///
191
      /// This function will fail if this point is the identity element
192
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
193
0
      T xy_bytes() const {
194
0
         T bytes(2 * this->field_element_bytes());
195
0
         this->serialize_xy_to(bytes);
196
0
         return bytes;
197
0
      }
Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEET_v
Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS3_9allocatorIhEEEEEET_v
198
199
      /// Return the bytes of the affine x and y coordinates in a container
200
      ///
201
      /// This function will fail if this point is the identity element
202
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
203
20.2k
      T serialize_uncompressed() const {
204
20.2k
         T bytes(1 + 2 * this->field_element_bytes());
205
20.2k
         this->serialize_uncompressed_to(bytes);
206
20.2k
         return bytes;
207
20.2k
      }
208
209
      /// Return the bytes of the affine x and y coordinates in a container
210
      ///
211
      /// This function will fail if this point is the identity element
212
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
213
9
      T serialize_compressed() const {
214
9
         T bytes(1 + this->field_element_bytes());
215
9
         this->serialize_compressed_to(bytes);
216
9
         return bytes;
217
9
      }
218
219
      bool operator==(const EC_AffinePoint& other) const;
220
221
668
      bool operator!=(const EC_AffinePoint& other) const { return !(*this == other); }
222
223
      /// Return an encoding depending on the requested format
224
      std::vector<uint8_t> serialize(EC_Point_Format format) const;
225
226
      EC_AffinePoint(const EC_AffinePoint& other);
227
      EC_AffinePoint(EC_AffinePoint&& other) noexcept;
228
229
      EC_AffinePoint& operator=(const EC_AffinePoint& other);
230
      EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept;
231
232
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
233
      /**
234
      * Deprecated conversion
235
      */
236
      EC_AffinePoint(const EC_Group& group, const EC_Point& pt);
237
238
      /**
239
      * Deprecated conversion
240
      */
241
      EC_Point to_legacy_point() const;
242
#endif
243
244
      BOTAN_DEPRECATED("Use version without workspace arg")
245
501
      static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) {
246
501
         return EC_AffinePoint::g_mul(scalar, rng);
247
501
      }
248
249
      BOTAN_DEPRECATED("Use version without workspace arg")
250
501
      EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) const {
251
501
         return this->mul(scalar, rng);
252
501
      }
253
254
      /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only
255
      secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar,
256
                                        RandomNumberGenerator& rng,
257
0
                                        std::vector<BigInt>& /*ws*/) const {
258
0
         return this->mul_x_only(scalar, rng);
259
0
      }
260
261
      ~EC_AffinePoint();
262
263
2.97k
      const EC_AffinePoint_Data& _inner() const { return inner(); }
264
265
      static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner);
266
267
      const std::shared_ptr<const EC_Group_Data>& _group() const;
268
269
   private:
270
      friend class EC_Mul2Table;
271
272
      explicit EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point);
273
274
94.5k
      const EC_AffinePoint_Data& inner() const { return *m_point; }
275
276
      std::unique_ptr<EC_AffinePoint_Data> m_point;
277
};
278
279
}  // namespace Botan
280
281
#endif