Coverage Report

Created: 2023-06-07 07:00

/src/botan/build/include/botan/ec_group.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* ECC Domain Parameters
3
*
4
* (C) 2007 Falko Strenzke, FlexSecure GmbH
5
*     2008-2010 Jack Lloyd
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9
10
#ifndef BOTAN_ECC_DOMAIN_PARAMETERS_H_
11
#define BOTAN_ECC_DOMAIN_PARAMETERS_H_
12
13
#include <botan/asn1_obj.h>
14
#include <botan/ec_point.h>
15
#include <memory>
16
#include <set>
17
#include <span>
18
19
namespace Botan {
20
21
/**
22
* This class represents elliptic curce domain parameters
23
*/
24
enum class EC_Group_Encoding {
25
   Explicit,
26
   ImplicitCA,
27
   NamedCurve,
28
29
   EC_DOMPAR_ENC_EXPLICIT = Explicit,
30
   EC_DOMPAR_ENC_IMPLICITCA = ImplicitCA,
31
   EC_DOMPAR_ENC_OID = NamedCurve
32
};
33
34
enum class EC_Group_Source {
35
   Builtin,
36
   ExternalSource,
37
};
38
39
class EC_Group_Data;
40
class EC_Group_Data_Map;
41
42
/**
43
* Class representing an elliptic curve
44
*
45
* The internal representation is stored in a shared_ptr, so copying an
46
* EC_Group is inexpensive.
47
*/
48
class BOTAN_PUBLIC_API(2, 0) EC_Group final {
49
   public:
50
      /**
51
      * Construct Domain paramers from specified parameters
52
      * @param p the elliptic curve p
53
      * @param a the elliptic curve a param
54
      * @param b the elliptic curve b param
55
      * @param base_x the x coordinate of the base point
56
      * @param base_y the y coordinate of the base point
57
      * @param order the order of the base point
58
      * @param cofactor the cofactor
59
      * @param oid an optional OID used to identify this curve
60
      */
61
      EC_Group(const BigInt& p,
62
               const BigInt& a,
63
               const BigInt& b,
64
               const BigInt& base_x,
65
               const BigInt& base_y,
66
               const BigInt& order,
67
               const BigInt& cofactor,
68
               const OID& oid = OID());
69
70
      /**
71
      * Decode a BER encoded ECC domain parameter set
72
      * @param ber the bytes of the BER encoding
73
      * @param ber_len the length of ber
74
      */
75
      explicit EC_Group(const uint8_t ber[], size_t ber_len);
76
77
      template <typename Alloc>
78
      EC_Group(const std::vector<uint8_t, Alloc>& ber) : EC_Group(ber.data(), ber.size()) {}
79
80
      /**
81
      * Create an EC domain by OID (or throw if unknown)
82
      * @param oid the OID of the EC domain to create
83
      */
84
      explicit EC_Group(const OID& oid);
85
86
      /**
87
      * Create an EC domain from PEM encoding (as from PEM_encode), or
88
      * from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7")
89
      * @param pem_or_oid PEM-encoded data, or an OID
90
91
      * @warning Support for PEM in this function is deprecated. Use
92
      * EC_Group_from_PEM
93
      */
94
      explicit EC_Group(std::string_view pem_or_oid);
95
96
      static EC_Group EC_Group_from_PEM(std::string_view pem);
97
98
      /**
99
      * Create an uninitialized EC_Group
100
      */
101
      EC_Group();
102
103
      ~EC_Group();
104
105
      EC_Group(const EC_Group&) = default;
106
      EC_Group(EC_Group&&) = default;
107
108
      EC_Group& operator=(const EC_Group&) = default;
109
      EC_Group& operator=(EC_Group&&) = default;
110
111
      /**
112
      * Create the DER encoding of this domain
113
      * @param form of encoding to use
114
      * @returns bytes encododed as DER
115
      */
116
      std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const;
117
118
      /**
119
      * Return the PEM encoding (always in explicit form)
120
      * @return string containing PEM data
121
      */
122
      std::string PEM_encode() const;
123
124
      /**
125
      * Return if a == -3 mod p
126
      */
127
      bool a_is_minus_3() const;
128
129
      /**
130
      * Return if a == 0 mod p
131
      */
132
      bool a_is_zero() const;
133
134
      /**
135
      * Return the size of p in bits (same as get_p().bits())
136
      */
137
      size_t get_p_bits() const;
138
139
      /**
140
      * Return the size of p in bits (same as get_p().bytes())
141
      */
142
      size_t get_p_bytes() const;
143
144
      /**
145
      * Return the size of group order in bits (same as get_order().bits())
146
      */
147
      size_t get_order_bits() const;
148
149
      /**
150
      * Return the size of p in bytes (same as get_order().bytes())
151
      */
152
      size_t get_order_bytes() const;
153
154
      /**
155
      * Return the prime modulus of the field
156
      */
157
      const BigInt& get_p() const;
158
159
      /**
160
      * Return the a parameter of the elliptic curve equation
161
      */
162
      const BigInt& get_a() const;
163
164
      /**
165
      * Return the b parameter of the elliptic curve equation
166
      */
167
      const BigInt& get_b() const;
168
169
      /**
170
      * Return group base point
171
      * @result base point
172
      */
173
      const EC_Point& get_base_point() const;
174
175
      /**
176
      * Return the x coordinate of the base point
177
      */
178
      const BigInt& get_g_x() const;
179
180
      /**
181
      * Return the y coordinate of the base point
182
      */
183
      const BigInt& get_g_y() const;
184
185
      /**
186
      * Return the order of the base point
187
      * @result order of the base point
188
      */
189
      const BigInt& get_order() const;
190
191
      /**
192
      * Return the cofactor
193
      * @result the cofactor
194
      */
195
      const BigInt& get_cofactor() const;
196
197
      /*
198
      * Reduce x modulo the order
199
      */
200
      BigInt mod_order(const BigInt& x) const;
201
202
      /*
203
      * Return inverse of x modulo the order
204
      */
205
      BigInt inverse_mod_order(const BigInt& x) const;
206
207
      /*
208
      * Reduce (x*x) modulo the order
209
      */
210
      BigInt square_mod_order(const BigInt& x) const;
211
212
      /*
213
      * Reduce (x*y) modulo the order
214
      */
215
      BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const;
216
217
      /*
218
      * Reduce (x*y*z) modulo the order
219
      */
220
      BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const;
221
222
      /*
223
      * Return x^3 modulo the order
224
      */
225
0
      inline BigInt cube_mod_order(const BigInt& x) const { return multiply_mod_order(x, square_mod_order(x)); }
226
227
      /**
228
      * Check if y is a plausible point on the curve
229
      *
230
      * In particular, checks that it is a point on the curve, not infinity,
231
      * and that it has order matching the group.
232
      */
233
      bool verify_public_element(const EC_Point& y) const;
234
235
      /**
236
      * Return the OID of these domain parameters
237
      * @result the OID
238
      */
239
      const OID& get_curve_oid() const;
240
241
      /**
242
      * Return a point on this curve with the affine values x, y
243
      */
244
      EC_Point point(const BigInt& x, const BigInt& y) const;
245
246
      /**
247
      * Multi exponentiate. Not constant time.
248
      * @return base_point*x + pt*y
249
      */
250
      EC_Point point_multiply(const BigInt& x, const EC_Point& pt, const BigInt& y) const;
251
252
      /**
253
      * Blinded point multiplication, attempts resistance to side channels
254
      * @param k the scalar
255
      * @param rng a random number generator
256
      * @param ws a temp workspace
257
      * @return base_point*k
258
      */
259
      EC_Point blinded_base_point_multiply(const BigInt& k, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const;
260
261
      /**
262
      * Blinded point multiplication, attempts resistance to side channels
263
      * Returns just the x coordinate of the point
264
      *
265
      * @param k the scalar
266
      * @param rng a random number generator
267
      * @param ws a temp workspace
268
      * @return x coordinate of base_point*k
269
      */
270
      BigInt blinded_base_point_multiply_x(const BigInt& k, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const;
271
272
      /**
273
      * Blinded point multiplication, attempts resistance to side channels
274
      * @param point input point
275
      * @param k the scalar
276
      * @param rng a random number generator
277
      * @param ws a temp workspace
278
      * @return point*k
279
      */
280
      EC_Point blinded_var_point_multiply(const EC_Point& point,
281
                                          const BigInt& k,
282
                                          RandomNumberGenerator& rng,
283
                                          std::vector<BigInt>& ws) const;
284
285
      /**
286
      * Return a random scalar ie an integer in [1,order)
287
      */
288
      BigInt random_scalar(RandomNumberGenerator& rng) const;
289
290
      /**
291
      * Hash onto the curve.
292
      * For some curve types no mapping is currently available, in this
293
      * case this function will throw an exception.
294
      *
295
      * @param hash_fn the hash function to use (typically "SHA-256" or "SHA-512")
296
      * @param input the input to hash
297
      * @param input_len length of input in bytes
298
      * @param domain_sep a domain seperator
299
      * @param domain_sep_len length of domain_sep in bytes
300
      * @param random_oracle if the mapped point must be uniform (use
301
               "true" here unless you know what you are doing)
302
      */
303
      EC_Point hash_to_curve(std::string_view hash_fn,
304
                             const uint8_t input[],
305
                             size_t input_len,
306
                             const uint8_t domain_sep[],
307
                             size_t domain_sep_len,
308
                             bool random_oracle = true) const;
309
310
      /**
311
      * Hash onto the curve.
312
      * For some curve types no mapping is currently available, in this
313
      * case this function will throw an exception.
314
      *
315
      * @param hash_fn the hash function to use (typically "SHA-256" or "SHA-512")
316
      * @param input the input to hash
317
      * @param input_len length of input in bytes
318
      * @param domain_sep a domain seperator
319
      * @param random_oracle if the mapped point must be uniform (use
320
               "true" here unless you know what you are doing)
321
      */
322
      EC_Point hash_to_curve(std::string_view hash_fn,
323
                             const uint8_t input[],
324
                             size_t input_len,
325
                             std::string_view domain_sep,
326
                             bool random_oracle = true) const;
327
328
      /**
329
      * Return the zero (or infinite) point on this curve
330
      */
331
      EC_Point zero_point() const;
332
333
      size_t point_size(EC_Point_Format format) const;
334
335
      EC_Point OS2ECP(const uint8_t bits[], size_t len) const;
336
337
0
      EC_Point OS2ECP(std::span<const uint8_t> encoded_point) const {
338
0
         return this->OS2ECP(encoded_point.data(), encoded_point.size());
339
0
      }
340
341
0
      bool initialized() const { return (m_data != nullptr); }
342
343
      /**
344
       * Verify EC_Group domain
345
       * @returns true if group is valid. false otherwise
346
       */
347
      bool verify_group(RandomNumberGenerator& rng, bool strong = false) const;
348
349
      bool operator==(const EC_Group& other) const;
350
351
      EC_Group_Source source() const;
352
353
      /**
354
      * Return a set of known named EC groups
355
      */
356
      static const std::set<std::string>& known_named_groups();
357
358
      /*
359
      * For internal use only
360
      */
361
      static std::shared_ptr<EC_Group_Data> EC_group_info(const OID& oid);
362
363
      /*
364
      * For internal use only
365
      */
366
      static size_t clear_registered_curve_data();
367
368
      /*
369
      * For internal use only
370
      */
371
      static OID EC_group_identity_from_order(const BigInt& order);
372
373
   private:
374
      static EC_Group_Data_Map& ec_group_data();
375
376
      static std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const uint8_t bits[],
377
                                                                size_t len,
378
                                                                EC_Group_Source source);
379
380
      static std::shared_ptr<EC_Group_Data> load_EC_group_info(const char* p,
381
                                                               const char* a,
382
                                                               const char* b,
383
                                                               const char* g_x,
384
                                                               const char* g_y,
385
                                                               const char* order,
386
                                                               const OID& oid);
387
388
      // Member data
389
      const EC_Group_Data& data() const;
390
      std::shared_ptr<EC_Group_Data> m_data;
391
};
392
393
0
inline bool operator!=(const EC_Group& lhs, const EC_Group& rhs) { return !(lhs == rhs); }
394
395
}  // namespace Botan
396
397
#endif