Botan 3.6.0
Crypto and TLS for C&
ec_inner_data.h
Go to the documentation of this file.
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_INNER_DATA_H_
8#define BOTAN_EC_INNER_DATA_H_
9
10#include <botan/ec_group.h>
11
12#include <botan/asn1_obj.h>
13#include <botan/bigint.h>
14#include <botan/reducer.h>
15#include <botan/internal/stl_util.h>
16#include <memory>
17#include <span>
18
19namespace Botan {
20
21class EC_Point_Base_Point_Precompute;
22
23namespace PCurve {
24
25class PrimeOrderCurve;
26
27}
28
29class EC_Group_Data;
30
32 public:
33 virtual ~EC_Scalar_Data() = default;
34
35 virtual const std::shared_ptr<const EC_Group_Data>& group() const = 0;
36
37 virtual size_t bytes() const = 0;
38
39 virtual std::unique_ptr<EC_Scalar_Data> clone() const = 0;
40
41 virtual bool is_zero() const = 0;
42
43 virtual bool is_eq(const EC_Scalar_Data& y) const = 0;
44
45 virtual void assign(const EC_Scalar_Data& y) = 0;
46
47 virtual void square_self() = 0;
48
49 virtual std::unique_ptr<EC_Scalar_Data> negate() const = 0;
50
51 virtual std::unique_ptr<EC_Scalar_Data> invert() const = 0;
52
53 virtual std::unique_ptr<EC_Scalar_Data> add(const EC_Scalar_Data& other) const = 0;
54
55 virtual std::unique_ptr<EC_Scalar_Data> sub(const EC_Scalar_Data& other) const = 0;
56
57 virtual std::unique_ptr<EC_Scalar_Data> mul(const EC_Scalar_Data& other) const = 0;
58
59 virtual void serialize_to(std::span<uint8_t> bytes) const = 0;
60};
61
63 public:
64 virtual ~EC_AffinePoint_Data() = default;
65
66 virtual const std::shared_ptr<const EC_Group_Data>& group() const = 0;
67
68 virtual std::unique_ptr<EC_AffinePoint_Data> clone() const = 0;
69
70 // Return size of a field element
71 virtual size_t field_element_bytes() const = 0;
72
73 // Return if this is the identity element
74 virtual bool is_identity() const = 0;
75
76 // Writes 1 field element worth of data to bytes
77 virtual void serialize_x_to(std::span<uint8_t> bytes) const = 0;
78
79 // Writes 1 field element worth of data to bytes
80 virtual void serialize_y_to(std::span<uint8_t> bytes) const = 0;
81
82 // Writes 2 field elements worth of data to bytes
83 virtual void serialize_xy_to(std::span<uint8_t> bytes) const = 0;
84
85 // Writes 1 byte + 1 field element worth of data to bytes
86 virtual void serialize_compressed_to(std::span<uint8_t> bytes) const = 0;
87
88 // Writes 1 byte + 2 field elements worth of data to bytes
89 virtual void serialize_uncompressed_to(std::span<uint8_t> bytes) const = 0;
90
91 virtual std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar,
93 std::vector<BigInt>& ws) const = 0;
94
95 virtual EC_Point to_legacy_point() const = 0;
96};
97
99 public:
100 virtual ~EC_Mul2Table_Data() = default;
101
102 // Returns nullptr if g*x + h*y was point at infinity
103 virtual std::unique_ptr<EC_AffinePoint_Data> mul2_vartime(const EC_Scalar_Data& x,
104 const EC_Scalar_Data& y) const = 0;
105
106 // Check if v == (g*x + h*y).x % n
107 //
108 // Returns false if g*x + h*y was point at infinity
110 const EC_Scalar_Data& x,
111 const EC_Scalar_Data& y) const = 0;
112};
113
114class EC_Group_Data final : public std::enable_shared_from_this<EC_Group_Data> {
115 public:
116 EC_Group_Data(const BigInt& p,
117 const BigInt& a,
118 const BigInt& b,
119 const BigInt& g_x,
120 const BigInt& g_y,
121 const BigInt& order,
122 const BigInt& cofactor,
123 const OID& oid,
125
127
128 bool params_match(const BigInt& p,
129 const BigInt& a,
130 const BigInt& b,
131 const BigInt& g_x,
132 const BigInt& g_y,
133 const BigInt& order,
134 const BigInt& cofactor) const;
135
136 bool params_match(const EC_Group_Data& other) const;
137
138 void set_oid(const OID& oid);
139
140 const OID& oid() const { return m_oid; }
141
142 const std::vector<uint8_t>& der_named_curve() const { return m_der_named_curve; }
143
144 const BigInt& p() const { return m_curve.get_p(); }
145
146 const BigInt& a() const { return m_curve.get_a(); }
147
148 const BigInt& b() const { return m_curve.get_b(); }
149
150 const BigInt& order() const { return m_order; }
151
152 const BigInt& cofactor() const { return m_cofactor; }
153
154 bool order_is_less_than_p() const { return m_order_is_less_than_p; }
155
156 bool has_cofactor() const { return m_has_cofactor; }
157
158 const BigInt& g_x() const { return m_g_x; }
159
160 const BigInt& g_y() const { return m_g_y; }
161
162 size_t p_bits() const { return m_p_bits; }
163
164 size_t p_bytes() const { return (m_p_bits + 7) / 8; }
165
166 size_t order_bits() const { return m_order_bits; }
167
168 size_t order_bytes() const { return m_order_bytes; }
169
170 const CurveGFp& curve() const { return m_curve; }
171
172 const EC_Point& base_point() const { return m_base_point; }
173
174 bool a_is_minus_3() const { return m_a_is_minus_3; }
175
176 bool a_is_zero() const { return m_a_is_zero; }
177
178 BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); }
179
180 BigInt square_mod_order(const BigInt& x) const { return m_mod_order.square(x); }
181
182 BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const { return m_mod_order.multiply(x, y); }
183
184 BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const {
185 return m_mod_order.multiply(m_mod_order.multiply(x, y), z);
186 }
187
188 BigInt inverse_mod_order(const BigInt& x) const { return inverse_mod(x, m_order); }
189
190 EC_Group_Source source() const { return m_source; }
191
192 /// Scalar from bytes
193 ///
194 /// This returns a value only if the bytes represent (in big-endian encoding) an integer
195 /// that is less than n, where n is the group order. It requires that the fixed length
196 /// encoding (with zero prefix) be used. It also rejects inputs that encode zero.
197 /// Thus the accepted range is [1,n)
198 ///
199 /// If the input is rejected then nullptr is returned
200 std::unique_ptr<EC_Scalar_Data> scalar_deserialize(std::span<const uint8_t> bytes) const;
201
202 /// Scalar from bytes with ECDSA style trunction
203 ///
204 /// This should always succeed
205 std::unique_ptr<EC_Scalar_Data> scalar_from_bytes_with_trunc(std::span<const uint8_t> bytes) const;
206
207 /// Scalar from bytes with modular reduction
208 ///
209 /// This returns a value only if bytes represents (in big-endian encoding) an integer
210 /// that is at most the square of the scalar group size. Otherwise it returns nullptr.
211 std::unique_ptr<EC_Scalar_Data> scalar_from_bytes_mod_order(std::span<const uint8_t> bytes) const;
212
213 /// Scalar from BigInt
214 ///
215 /// This returns a value only if bn is in [1,n) where n is the group order.
216 /// Otherwise it returns nullptr
217 std::unique_ptr<EC_Scalar_Data> scalar_from_bigint(const BigInt& bn) const;
218
219 /// Return a random scalar
220 ///
221 /// This will be in the range [1,n) where n is the group order
222 std::unique_ptr<EC_Scalar_Data> scalar_random(RandomNumberGenerator& rng) const;
223
224 std::unique_ptr<EC_Scalar_Data> scalar_zero() const;
225
226 std::unique_ptr<EC_Scalar_Data> scalar_one() const;
227
228 std::unique_ptr<EC_Scalar_Data> gk_x_mod_order(const EC_Scalar_Data& scalar,
230 std::vector<BigInt>& ws) const;
231
232 /// Deserialize a point
233 ///
234 /// Returns nullptr if the point encoding was invalid or not on the curve
235 std::unique_ptr<EC_AffinePoint_Data> point_deserialize(std::span<const uint8_t> bytes) const;
236
237 std::unique_ptr<EC_AffinePoint_Data> point_hash_to_curve_ro(std::string_view hash_fn,
238 std::span<const uint8_t> input,
239 std::span<const uint8_t> domain_sep) const;
240
241 std::unique_ptr<EC_AffinePoint_Data> point_hash_to_curve_nu(std::string_view hash_fn,
242 std::span<const uint8_t> input,
243 std::span<const uint8_t> domain_sep) const;
244
245 std::unique_ptr<EC_AffinePoint_Data> point_g_mul(const EC_Scalar_Data& scalar,
247 std::vector<BigInt>& ws) const;
248
249 std::unique_ptr<EC_Mul2Table_Data> make_mul2_table(const EC_AffinePoint_Data& pt) const;
250
252 BOTAN_ASSERT_NONNULL(m_pcurve);
253 return *m_pcurve;
254 }
255
256 private:
257 // Possibly nullptr (if pcurves not available or not a standard curve)
258 std::shared_ptr<const PCurve::PrimeOrderCurve> m_pcurve;
259
260 // Set only if m_pcurve is nullptr
261 std::unique_ptr<EC_Point_Base_Point_Precompute> m_base_mult;
262
263 CurveGFp m_curve;
264 EC_Point m_base_point;
265
266 BigInt m_g_x;
267 BigInt m_g_y;
268 BigInt m_order;
269 BigInt m_cofactor;
270 Modular_Reducer m_mod_order;
271 OID m_oid;
272 std::vector<uint8_t> m_der_named_curve;
273 size_t m_p_bits;
274 size_t m_order_bits;
275 size_t m_order_bytes;
276 bool m_a_is_minus_3;
277 bool m_a_is_zero;
278 bool m_has_cofactor;
279 bool m_order_is_less_than_p;
280 EC_Group_Source m_source;
281};
282
283} // namespace Botan
284
285#endif
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
const BigInt & get_a() const
Definition curve_gfp.h:98
const BigInt & get_p() const
Definition curve_gfp.h:109
const BigInt & get_b() const
Definition curve_gfp.h:103
virtual void serialize_compressed_to(std::span< uint8_t > bytes) const =0
virtual ~EC_AffinePoint_Data()=default
virtual void serialize_y_to(std::span< uint8_t > bytes) const =0
virtual std::unique_ptr< EC_AffinePoint_Data > clone() const =0
virtual size_t field_element_bytes() const =0
virtual void serialize_uncompressed_to(std::span< uint8_t > bytes) const =0
virtual void serialize_x_to(std::span< uint8_t > bytes) const =0
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
virtual EC_Point to_legacy_point() const =0
virtual bool is_identity() const =0
virtual void serialize_xy_to(std::span< uint8_t > bytes) const =0
virtual std::unique_ptr< EC_AffinePoint_Data > mul(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const =0
const BigInt & p() const
const BigInt & g_x() const
std::unique_ptr< EC_Scalar_Data > gk_x_mod_order(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
const BigInt & a() const
std::unique_ptr< EC_Scalar_Data > scalar_from_bytes_mod_order(std::span< const uint8_t > bytes) const
std::unique_ptr< EC_AffinePoint_Data > point_deserialize(std::span< const uint8_t > bytes) const
bool a_is_minus_3() const
std::unique_ptr< EC_Scalar_Data > scalar_random(RandomNumberGenerator &rng) const
std::unique_ptr< EC_Scalar_Data > scalar_zero() const
bool has_cofactor() const
std::unique_ptr< EC_Scalar_Data > scalar_deserialize(std::span< const uint8_t > bytes) const
bool params_match(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &g_x, const BigInt &g_y, const BigInt &order, const BigInt &cofactor) const
const PCurve::PrimeOrderCurve & pcurve() const
EC_Group_Data(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &g_x, const BigInt &g_y, const BigInt &order, const BigInt &cofactor, const OID &oid, EC_Group_Source source)
std::unique_ptr< EC_Scalar_Data > scalar_from_bytes_with_trunc(std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Mul2Table_Data > make_mul2_table(const EC_AffinePoint_Data &pt) const
std::unique_ptr< EC_Scalar_Data > scalar_one() const
const OID & oid() const
const EC_Point & base_point() const
size_t order_bits() const
const BigInt & cofactor() const
std::unique_ptr< EC_AffinePoint_Data > point_g_mul(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
const CurveGFp & curve() const
BigInt inverse_mod_order(const BigInt &x) const
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
BigInt multiply_mod_order(const BigInt &x, const BigInt &y, const BigInt &z) const
const std::vector< uint8_t > & der_named_curve() const
bool order_is_less_than_p() const
size_t p_bytes() const
EC_Group_Source source() const
void set_oid(const OID &oid)
BigInt square_mod_order(const BigInt &x) const
const BigInt & g_y() const
size_t order_bytes() const
std::unique_ptr< EC_Scalar_Data > scalar_from_bigint(const BigInt &bn) const
std::unique_ptr< EC_AffinePoint_Data > point_hash_to_curve_ro(std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
size_t p_bits() const
const BigInt & b() const
BigInt mod_order(const BigInt &x) const
std::unique_ptr< EC_AffinePoint_Data > point_hash_to_curve_nu(std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
const BigInt & order() const
virtual ~EC_Mul2Table_Data()=default
virtual bool mul2_vartime_x_mod_order_eq(const EC_Scalar_Data &v, const EC_Scalar_Data &x, const EC_Scalar_Data &y) const =0
virtual std::unique_ptr< EC_AffinePoint_Data > mul2_vartime(const EC_Scalar_Data &x, const EC_Scalar_Data &y) const =0
virtual void assign(const EC_Scalar_Data &y)=0
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
virtual size_t bytes() const =0
virtual std::unique_ptr< EC_Scalar_Data > sub(const EC_Scalar_Data &other) const =0
virtual std::unique_ptr< EC_Scalar_Data > invert() const =0
virtual void serialize_to(std::span< uint8_t > bytes) const =0
virtual std::unique_ptr< EC_Scalar_Data > negate() const =0
virtual std::unique_ptr< EC_Scalar_Data > clone() const =0
virtual std::unique_ptr< EC_Scalar_Data > add(const EC_Scalar_Data &other) const =0
virtual void square_self()=0
virtual bool is_eq(const EC_Scalar_Data &y) const =0
virtual bool is_zero() const =0
virtual ~EC_Scalar_Data()=default
virtual std::unique_ptr< EC_Scalar_Data > mul(const EC_Scalar_Data &other) const =0
BigInt square(const BigInt &x) const
Definition reducer.h:45
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition reducer.h:32
BigInt reduce(const BigInt &x) const
Definition reducer.cpp:37
int(* final)(unsigned char *, CTX *)
EC_Group_Source
Definition ec_group.h:36
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition mod_inv.cpp:179