Coverage Report

Created: 2025-04-11 06:45

/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_UNSTABLE_API 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), non uniform variant
72
      ///
73
      /// Only supported for specific groups
74
      static EC_AffinePoint hash_to_curve_nu(const EC_Group& group,
75
                                             std::string_view hash_fn,
76
                                             std::span<const uint8_t> input,
77
                                             std::span<const uint8_t> domain_sep);
78
79
      /// Multiply a point by a scalar returning a complete point
80
      EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;
81
82
      /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only
83
      secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;
84
85
      /// Compute 2-ary multiscalar multiplication - p*x + q*y
86
      ///
87
      /// This operation runs in constant time with respect to p, x, q, and y
88
      ///
89
      /// @returns p*x+q*y, or nullopt if the result was the point at infinity
90
      static std::optional<EC_AffinePoint> mul_px_qy(const EC_AffinePoint& p,
91
                                                     const EC_Scalar& x,
92
                                                     const EC_AffinePoint& q,
93
                                                     const EC_Scalar& y,
94
                                                     RandomNumberGenerator& rng);
95
96
      /// Point addition
97
      ///
98
      /// Note that this is quite slow since it converts the resulting
99
      /// projective point immediately to affine coordinates, which requires a
100
      /// field inversion. This can be sufficient when implementing protocols
101
      /// that just need to perform a few additions.
102
      ///
103
      /// In the future a cooresponding EC_ProjectivePoint type may be added
104
      /// which would avoid the expensive affine conversions
105
      EC_AffinePoint add(const EC_AffinePoint& q) const;
106
107
      /// Point negation
108
      EC_AffinePoint negate() const;
109
110
      /// Return the number of bytes of a field element
111
      ///
112
      /// A point consists of two field elements, plus possibly a header
113
      size_t field_element_bytes() const;
114
115
      /// Return true if this point is the identity element
116
      bool is_identity() const;
117
118
      /// Write the fixed length encoding of affine x coordinate
119
      ///
120
      /// The output span must be exactly field_element_bytes long
121
      ///
122
      /// This function will fail if this point is the identity element
123
      void serialize_x_to(std::span<uint8_t> bytes) const;
124
125
      /// Write the fixed length encoding of affine y coordinate
126
      ///
127
      /// The output span must be exactly field_element_bytes long
128
      ///
129
      /// This function will fail if this point is the identity element
130
      void serialize_y_to(std::span<uint8_t> bytes) const;
131
132
      /// Write the fixed length encoding of affine x and y coordinates
133
      ///
134
      /// The output span must be exactly 2*field_element_bytes long
135
      ///
136
      /// This function will fail if this point is the identity element
137
      void serialize_xy_to(std::span<uint8_t> bytes) const;
138
139
      /// Write the fixed length SEC1 compressed encoding
140
      ///
141
      /// The output span must be exactly 1 + field_element_bytes long
142
      ///
143
      /// This function will fail if this point is the identity element
144
      void serialize_compressed_to(std::span<uint8_t> bytes) const;
145
146
      /// Return the fixed length encoding of SEC1 uncompressed encoding
147
      ///
148
      /// The output span must be exactly 1 + 2*field_element_bytes long
149
      ///
150
      /// This function will fail if this point is the identity element
151
      void serialize_uncompressed_to(std::span<uint8_t> bytes) const;
152
153
      /// Return the bytes of the affine x coordinate in a container
154
      ///
155
      /// This function will fail if this point is the identity element
156
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
157
0
      T x_bytes() const {
158
0
         T bytes(this->field_element_bytes());
159
0
         this->serialize_x_to(bytes);
160
0
         return bytes;
161
0
      }
162
163
      /// Return the bytes of the affine y coordinate in a container
164
      ///
165
      /// This function will fail if this point is the identity element
166
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
167
      T y_bytes() const {
168
         T bytes(this->field_element_bytes());
169
         this->serialize_y_to(bytes);
170
         return bytes;
171
      }
172
173
      /// Return the bytes of the affine x and y coordinates in a container
174
      ///
175
      /// This function will fail if this point is the identity element
176
      template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>>
177
      T xy_bytes() const {
178
         T bytes(2 * this->field_element_bytes());
179
         this->serialize_xy_to(bytes);
180
         return bytes;
181
      }
182
183
      /// Return the bytes of the affine x and y coordinates in a container
184
      ///
185
      /// This function will fail if this point is the identity element
186
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
187
0
      T serialize_uncompressed() const {
188
0
         T bytes(1 + 2 * this->field_element_bytes());
189
0
         this->serialize_uncompressed_to(bytes);
190
0
         return bytes;
191
0
      }
192
193
      /// Return the bytes of the affine x and y coordinates in a container
194
      ///
195
      /// This function will fail if this point is the identity element
196
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
197
0
      T serialize_compressed() const {
198
0
         T bytes(1 + this->field_element_bytes());
199
0
         this->serialize_compressed_to(bytes);
200
0
         return bytes;
201
0
      }
202
203
      bool operator==(const EC_AffinePoint& other) const;
204
205
0
      bool operator!=(const EC_AffinePoint& other) const { return !(*this == other); }
206
207
      /// Return an encoding depending on the requested format
208
      std::vector<uint8_t> serialize(EC_Point_Format format) const;
209
210
      EC_AffinePoint(const EC_AffinePoint& other);
211
      EC_AffinePoint(EC_AffinePoint&& other) noexcept;
212
213
      EC_AffinePoint& operator=(const EC_AffinePoint& other);
214
      EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept;
215
216
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
217
      /**
218
      * Deprecated conversion
219
      */
220
      EC_AffinePoint(const EC_Group& group, const EC_Point& pt);
221
222
      /**
223
      * Deprecated conversion
224
      */
225
      EC_Point to_legacy_point() const;
226
#endif
227
228
      BOTAN_DEPRECATED("Use version without workspace arg")
229
0
      static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>&) {
230
0
         return EC_AffinePoint::g_mul(scalar, rng);
231
0
      }
232
233
      BOTAN_DEPRECATED("Use version without workspace arg")
234
0
      EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>&) const {
235
0
         return this->mul(scalar, rng);
236
0
      }
237
238
      /// Multiply a point by a scalar, returning the byte encoding of the x coordinate only
239
      secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar,
240
                                        RandomNumberGenerator& rng,
241
0
                                        std::vector<BigInt>&) const {
242
0
         return this->mul_x_only(scalar, rng);
243
0
      }
244
245
      ~EC_AffinePoint();
246
247
1.18k
      const EC_AffinePoint_Data& _inner() const { return inner(); }
248
249
      static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner);
250
251
      const std::shared_ptr<const EC_Group_Data>& _group() const;
252
253
   private:
254
      friend class EC_Mul2Table;
255
256
      EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point);
257
258
4.66k
      const EC_AffinePoint_Data& inner() const { return *m_point; }
259
260
      std::unique_ptr<EC_AffinePoint_Data> m_point;
261
};
262
263
}  // namespace Botan
264
265
#endif