/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/secmem.h> |
12 | | #include <botan/types.h> |
13 | | #include <optional> |
14 | | #include <span> |
15 | | #include <string_view> |
16 | | #include <vector> |
17 | | |
18 | | namespace Botan { |
19 | | |
20 | | class BigInt; |
21 | | class RandomNumberGenerator; |
22 | | class EC_Group; |
23 | | class EC_Scalar; |
24 | | class EC_Point; |
25 | | |
26 | | class EC_Group_Data; |
27 | | class EC_AffinePoint_Data; |
28 | | |
29 | | /// Elliptic Curve in Affine Representation |
30 | | /// |
31 | | class BOTAN_UNSTABLE_API EC_AffinePoint final { |
32 | | public: |
33 | | /// Point deserialization. Throws if wrong length or not a valid point |
34 | | /// |
35 | | /// This accepts SEC1 compressed or uncompressed formats |
36 | | EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes); |
37 | | |
38 | | /// Point deserialization. Returns nullopt if wrong length or not a valid point |
39 | | /// |
40 | | /// This accepts SEC1 compressed or uncompressed formats |
41 | | static std::optional<EC_AffinePoint> deserialize(const EC_Group& group, std::span<const uint8_t> bytes); |
42 | | |
43 | | /// Create a point from a pair (x,y) of integers |
44 | | /// |
45 | | /// The integers must be within the field - in the range [0,p) and must |
46 | | /// satisfy the curve equation |
47 | | static std::optional<EC_AffinePoint> from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y); |
48 | | |
49 | | /// Multiply by the group generator returning a complete point |
50 | | /// |
51 | | /// Workspace argument is transitional |
52 | | static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws); |
53 | | |
54 | | /// Return the identity element |
55 | | static EC_AffinePoint identity(const EC_Group& group); |
56 | | |
57 | | /// Return the standard group generator |
58 | | static EC_AffinePoint generator(const EC_Group& group); |
59 | | |
60 | | /// Hash to curve (RFC 9380), random oracle variant |
61 | | /// |
62 | | /// Only supported for specific groups |
63 | | static EC_AffinePoint hash_to_curve_ro(const EC_Group& group, |
64 | | std::string_view hash_fn, |
65 | | std::span<const uint8_t> input, |
66 | | std::span<const uint8_t> domain_sep); |
67 | | |
68 | | /// Hash to curve (RFC 9380), non uniform variant |
69 | | /// |
70 | | /// Only supported for specific groups |
71 | | static EC_AffinePoint hash_to_curve_nu(const EC_Group& group, |
72 | | std::string_view hash_fn, |
73 | | std::span<const uint8_t> input, |
74 | | std::span<const uint8_t> domain_sep); |
75 | | |
76 | | /// Multiply a point by a scalar returning a complete point |
77 | | /// |
78 | | /// Workspace argument is transitional |
79 | | EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const; |
80 | | |
81 | | /// Compute 2-ary multiscalar multiplication - p*x + q*y |
82 | | /// |
83 | | /// This operation runs in constant time with respect to p, x, q, and y |
84 | | /// |
85 | | /// @returns p*x+q*y, or nullopt if the result was the point at infinity |
86 | | static std::optional<EC_AffinePoint> mul_px_qy(const EC_AffinePoint& p, |
87 | | const EC_Scalar& x, |
88 | | const EC_AffinePoint& q, |
89 | | const EC_Scalar& y, |
90 | | RandomNumberGenerator& rng); |
91 | | |
92 | | /// Point addition |
93 | | /// |
94 | | /// Note that this is quite slow since it converts the resulting |
95 | | /// projective point immediately to affine coordinates, which requires a |
96 | | /// field inversion. This can be sufficient when implementing protocols |
97 | | /// that just need to perform a few additions. |
98 | | /// |
99 | | /// In the future a cooresponding EC_ProjectivePoint type may be added |
100 | | /// which would avoid the expensive affine conversions |
101 | | EC_AffinePoint add(const EC_AffinePoint& q) const; |
102 | | |
103 | | /// Point negation |
104 | | EC_AffinePoint negate() const; |
105 | | |
106 | | /// Return the number of bytes of a field element |
107 | | /// |
108 | | /// A point consists of two field elements, plus possibly a header |
109 | | size_t field_element_bytes() const; |
110 | | |
111 | | /// Return true if this point is the identity element |
112 | | bool is_identity() const; |
113 | | |
114 | | /// Write the fixed length encoding of affine x coordinate |
115 | | /// |
116 | | /// The output span must be exactly field_element_bytes long |
117 | | /// |
118 | | /// This function will fail if this point is the identity element |
119 | | void serialize_x_to(std::span<uint8_t> bytes) const; |
120 | | |
121 | | /// Write the fixed length encoding of affine y coordinate |
122 | | /// |
123 | | /// The output span must be exactly field_element_bytes long |
124 | | /// |
125 | | /// This function will fail if this point is the identity element |
126 | | void serialize_y_to(std::span<uint8_t> bytes) const; |
127 | | |
128 | | /// Write the fixed length encoding of affine x and y coordinates |
129 | | /// |
130 | | /// The output span must be exactly 2*field_element_bytes long |
131 | | /// |
132 | | /// This function will fail if this point is the identity element |
133 | | void serialize_xy_to(std::span<uint8_t> bytes) const; |
134 | | |
135 | | /// Write the fixed length SEC1 compressed encoding |
136 | | /// |
137 | | /// The output span must be exactly 1 + field_element_bytes long |
138 | | /// |
139 | | /// This function will fail if this point is the identity element |
140 | | void serialize_compressed_to(std::span<uint8_t> bytes) const; |
141 | | |
142 | | /// Return the fixed length encoding of SEC1 uncompressed encoding |
143 | | /// |
144 | | /// The output span must be exactly 1 + 2*field_element_bytes long |
145 | | /// |
146 | | /// This function will fail if this point is the identity element |
147 | | void serialize_uncompressed_to(std::span<uint8_t> bytes) const; |
148 | | |
149 | | /// Return the bytes of the affine x coordinate in a container |
150 | | /// |
151 | | /// This function will fail if this point is the identity element |
152 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
153 | 173 | T x_bytes() const { |
154 | 173 | T bytes(this->field_element_bytes()); |
155 | 173 | this->serialize_x_to(bytes); |
156 | 173 | return bytes; |
157 | 173 | } |
158 | | |
159 | | /// Return the bytes of the affine y coordinate in a container |
160 | | /// |
161 | | /// This function will fail if this point is the identity element |
162 | | template <concepts::resizable_byte_buffer T = secure_vector<uint8_t>> |
163 | 0 | T y_bytes() const { |
164 | 0 | T bytes(this->field_element_bytes()); |
165 | 0 | this->serialize_y_to(bytes); |
166 | 0 | return bytes; |
167 | 0 | } |
168 | | |
169 | | /// Return the bytes of the affine x and y coordinates 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 xy_bytes() const { |
174 | 0 | T bytes(2 * this->field_element_bytes()); |
175 | 0 | this->serialize_xy_to(bytes); |
176 | 0 | return bytes; |
177 | 0 | } Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS_16secure_allocatorIhEEEEEET_v Unexecuted instantiation: _ZNK5Botan14EC_AffinePoint8xy_bytesITkNS_8concepts21resizable_byte_bufferENSt3__16vectorIhNS3_9allocatorIhEEEEEET_v |
178 | | |
179 | | /// Return the bytes of the affine x and y coordinates in a container |
180 | | /// |
181 | | /// This function will fail if this point is the identity element |
182 | | template <concepts::resizable_byte_buffer T = std::vector<uint8_t>> |
183 | 0 | T serialize_uncompressed() const { |
184 | 0 | T bytes(1 + 2 * this->field_element_bytes()); |
185 | 0 | this->serialize_uncompressed_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 = std::vector<uint8_t>> |
193 | | T serialize_compressed() const { |
194 | | T bytes(1 + this->field_element_bytes()); |
195 | | this->serialize_compressed_to(bytes); |
196 | | return bytes; |
197 | | } |
198 | | |
199 | | EC_AffinePoint(const EC_AffinePoint& other); |
200 | | EC_AffinePoint(EC_AffinePoint&& other) noexcept; |
201 | | |
202 | | EC_AffinePoint& operator=(const EC_AffinePoint& other); |
203 | | EC_AffinePoint& operator=(EC_AffinePoint&& other) noexcept; |
204 | | |
205 | | /** |
206 | | * Deprecated conversion |
207 | | */ |
208 | | EC_AffinePoint(const EC_Group& group, const EC_Point& pt); |
209 | | |
210 | | /** |
211 | | * Deprecated conversion |
212 | | */ |
213 | | EC_Point to_legacy_point() const; |
214 | | |
215 | | ~EC_AffinePoint(); |
216 | | |
217 | 773 | const EC_AffinePoint_Data& _inner() const { return inner(); } |
218 | | |
219 | | static EC_AffinePoint _from_inner(std::unique_ptr<EC_AffinePoint_Data> inner); |
220 | | |
221 | | const std::shared_ptr<const EC_Group_Data>& _group() const; |
222 | | |
223 | | private: |
224 | | friend class EC_Mul2Table; |
225 | | |
226 | | EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point); |
227 | | |
228 | 13.6k | const EC_AffinePoint_Data& inner() const { return *m_point; } |
229 | | |
230 | | std::unique_ptr<EC_AffinePoint_Data> m_point; |
231 | | }; |
232 | | |
233 | | } // namespace Botan |
234 | | |
235 | | #endif |