Botan 3.3.0
Crypto and TLS for C&
ec_group.cpp
Go to the documentation of this file.
1/*
2* ECC Domain Parameters
3*
4* (C) 2007 Falko Strenzke, FlexSecure GmbH
5* (C) 2008,2018 Jack Lloyd
6* (C) 2018 Tobias Niemann
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/ec_group.h>
12
13#include <botan/ber_dec.h>
14#include <botan/der_enc.h>
15#include <botan/mutex.h>
16#include <botan/pem.h>
17#include <botan/reducer.h>
18#include <botan/rng.h>
19#include <botan/internal/fmt.h>
20#include <botan/internal/point_mul.h>
21#include <botan/internal/primality.h>
22#include <vector>
23
24#if defined(BOTAN_HAS_EC_HASH_TO_CURVE)
25 #include <botan/internal/ec_h2c.h>
26#endif
27
28namespace Botan {
29
30class EC_Group_Data final {
31 public:
32 EC_Group_Data(const BigInt& p,
33 const BigInt& a,
34 const BigInt& b,
35 const BigInt& g_x,
36 const BigInt& g_y,
37 const BigInt& order,
38 const BigInt& cofactor,
39 const OID& oid,
40 EC_Group_Source source) :
41 m_curve(p, a, b),
42 m_base_point(m_curve, g_x, g_y),
43 m_g_x(g_x),
44 m_g_y(g_y),
45 m_order(order),
46 m_cofactor(cofactor),
47 m_mod_order(order),
48 m_base_mult(m_base_point, m_mod_order),
49 m_oid(oid),
50 m_p_bits(p.bits()),
51 m_order_bits(order.bits()),
52 m_a_is_minus_3(a == p - 3),
53 m_a_is_zero(a.is_zero()),
54 m_source(source) {}
55
56 bool params_match(const BigInt& p,
57 const BigInt& a,
58 const BigInt& b,
59 const BigInt& g_x,
60 const BigInt& g_y,
61 const BigInt& order,
62 const BigInt& cofactor) const {
63 return (this->p() == p && this->a() == a && this->b() == b && this->order() == order &&
64 this->cofactor() == cofactor && this->g_x() == g_x && this->g_y() == g_y);
65 }
66
67 bool params_match(const EC_Group_Data& other) const {
68 return params_match(
69 other.p(), other.a(), other.b(), other.g_x(), other.g_y(), other.order(), other.cofactor());
70 }
71
72 void set_oid(const OID& oid) {
73 BOTAN_STATE_CHECK(m_oid.empty());
74 m_oid = oid;
75 }
76
77 const OID& oid() const { return m_oid; }
78
79 const BigInt& p() const { return m_curve.get_p(); }
80
81 const BigInt& a() const { return m_curve.get_a(); }
82
83 const BigInt& b() const { return m_curve.get_b(); }
84
85 const BigInt& order() const { return m_order; }
86
87 const BigInt& cofactor() const { return m_cofactor; }
88
89 const BigInt& g_x() const { return m_g_x; }
90
91 const BigInt& g_y() const { return m_g_y; }
92
93 size_t p_bits() const { return m_p_bits; }
94
95 size_t p_bytes() const { return (m_p_bits + 7) / 8; }
96
97 size_t order_bits() const { return m_order_bits; }
98
99 size_t order_bytes() const { return (m_order_bits + 7) / 8; }
100
101 const CurveGFp& curve() const { return m_curve; }
102
103 const EC_Point& base_point() const { return m_base_point; }
104
105 bool a_is_minus_3() const { return m_a_is_minus_3; }
106
107 bool a_is_zero() const { return m_a_is_zero; }
108
109 BigInt mod_order(const BigInt& x) const { return m_mod_order.reduce(x); }
110
111 BigInt square_mod_order(const BigInt& x) const { return m_mod_order.square(x); }
112
113 BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const { return m_mod_order.multiply(x, y); }
114
115 BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const {
116 return m_mod_order.multiply(m_mod_order.multiply(x, y), z);
117 }
118
119 BigInt inverse_mod_order(const BigInt& x) const { return inverse_mod(x, m_order); }
120
121 EC_Point blinded_base_point_multiply(const BigInt& k, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const {
122 return m_base_mult.mul(k, rng, m_order, ws);
123 }
124
125 EC_Group_Source source() const { return m_source; }
126
127 private:
128 CurveGFp m_curve;
129 EC_Point m_base_point;
130
131 BigInt m_g_x;
132 BigInt m_g_y;
133 BigInt m_order;
134 BigInt m_cofactor;
135 Modular_Reducer m_mod_order;
136 EC_Point_Base_Point_Precompute m_base_mult;
137 OID m_oid;
138 size_t m_p_bits;
139 size_t m_order_bits;
140 bool m_a_is_minus_3;
141 bool m_a_is_zero;
142 EC_Group_Source m_source;
143};
144
145class EC_Group_Data_Map final {
146 public:
147 EC_Group_Data_Map() = default;
148
149 size_t clear() {
150 lock_guard_type<mutex_type> lock(m_mutex);
151 size_t count = m_registered_curves.size();
152 m_registered_curves.clear();
153 return count;
154 }
155
156 std::shared_ptr<EC_Group_Data> lookup(const OID& oid) {
157 lock_guard_type<mutex_type> lock(m_mutex);
158
159 for(auto i : m_registered_curves) {
160 if(i->oid() == oid) {
161 return i;
162 }
163 }
164
165 // Not found, check hardcoded data
166 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
167
168 if(data) {
169 for(auto curve : m_registered_curves) {
170 if(curve->oid().empty() == true && curve->params_match(*data)) {
171 curve->set_oid(oid);
172 return curve;
173 }
174 }
175
176 m_registered_curves.push_back(data);
177 return data;
178 }
179
180 // Nope, unknown curve
181 return std::shared_ptr<EC_Group_Data>();
182 }
183
184 std::shared_ptr<EC_Group_Data> lookup_or_create(const BigInt& p,
185 const BigInt& a,
186 const BigInt& b,
187 const BigInt& g_x,
188 const BigInt& g_y,
189 const BigInt& order,
190 const BigInt& cofactor,
191 const OID& oid,
192 EC_Group_Source source) {
193 lock_guard_type<mutex_type> lock(m_mutex);
194
195 for(auto i : m_registered_curves) {
196 /*
197 * The params may be the same but you are trying to register under a
198 * different OID than the one we are using, so using a different
199 * group, since EC_Group's model assumes a single OID per group.
200 */
201 if(!oid.empty() && !i->oid().empty() && i->oid() != oid) {
202 continue;
203 }
204
205 const bool same_oid = !oid.empty() && i->oid() == oid;
206 const bool same_params = i->params_match(p, a, b, g_x, g_y, order, cofactor);
207
208 /*
209 * If the params and OID are the same then we are done, just return
210 * the already registered curve obj.
211 */
212 if(same_params && same_oid) {
213 return i;
214 }
215
216 /*
217 * If same params and the new OID is empty, then that's ok too
218 */
219 if(same_params && oid.empty()) {
220 return i;
221 }
222
223 /*
224 * Check for someone trying to reuse an already in-use OID
225 */
226 if(same_oid && !same_params) {
227 throw Invalid_Argument("Attempting to register a curve using OID " + oid.to_string() +
228 " but a distinct curve is already registered using that OID");
229 }
230
231 /*
232 * If the same curve was previously created without an OID but is now
233 * being registered again using an OID, save that OID.
234 */
235 if(same_params && i->oid().empty() && !oid.empty()) {
236 i->set_oid(oid);
237 return i;
238 }
239 }
240
241 /*
242 Not found in current list, so we need to create a new entry
243
244 If an OID is set, try to look up relative our static tables to detect a duplicate
245 registration under an OID
246 */
247
248 std::shared_ptr<EC_Group_Data> new_group =
249 std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
250
251 if(oid.has_value()) {
252 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid);
253 if(data != nullptr && !new_group->params_match(*data)) {
254 throw Invalid_Argument("Attempting to register an EC group under OID of hardcoded group");
255 }
256 } else {
257 // Here try to use the order as a hint to look up the group id, to identify common groups
258 const OID oid_from_store = EC_Group::EC_group_identity_from_order(order);
259 if(oid_from_store.has_value()) {
260 std::shared_ptr<EC_Group_Data> data = EC_Group::EC_group_info(oid_from_store);
261
262 /*
263 If EC_group_identity_from_order returned an OID then looking up that OID
264 must always return a result.
265 */
266 BOTAN_ASSERT_NOMSG(data != nullptr);
267
268 /*
269 It is possible (if unlikely) that someone is registering another group
270 that happens to have an order equal to that of a well known group -
271 so verify all values before assigning the OID.
272 */
273 if(new_group->params_match(*data)) {
274 new_group->set_oid(oid_from_store);
275 }
276 }
277 }
278
279 m_registered_curves.push_back(new_group);
280 return new_group;
281 }
282
283 private:
284 mutex_type m_mutex;
285 std::vector<std::shared_ptr<EC_Group_Data>> m_registered_curves;
286};
287
288//static
289EC_Group_Data_Map& EC_Group::ec_group_data() {
290 /*
291 * This exists purely to ensure the allocator is constructed before g_ec_data,
292 * which ensures that its destructor runs after ~g_ec_data is complete.
293 */
294
295 static Allocator_Initializer g_init_allocator;
296 static EC_Group_Data_Map g_ec_data;
297 return g_ec_data;
298}
299
300//static
302 return ec_group_data().clear();
303}
304
305//static
306std::shared_ptr<EC_Group_Data> EC_Group::load_EC_group_info(const char* p_str,
307 const char* a_str,
308 const char* b_str,
309 const char* g_x_str,
310 const char* g_y_str,
311 const char* order_str,
312 const OID& oid) {
313 const BigInt p(p_str);
314 const BigInt a(a_str);
315 const BigInt b(b_str);
316 const BigInt g_x(g_x_str);
317 const BigInt g_y(g_y_str);
318 const BigInt order(order_str);
319 const BigInt cofactor(1); // implicit
320
321 return std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, EC_Group_Source::Builtin);
322}
323
324//static
325std::pair<std::shared_ptr<EC_Group_Data>, bool> EC_Group::BER_decode_EC_group(const uint8_t bits[],
326 size_t len,
327 EC_Group_Source source) {
328 BER_Decoder ber(bits, len);
329 BER_Object obj = ber.get_next_object();
330
331 if(obj.type() == ASN1_Type::ObjectId) {
332 OID dom_par_oid;
333 BER_Decoder(bits, len).decode(dom_par_oid);
334 return std::make_pair(ec_group_data().lookup(dom_par_oid), false);
335 }
336
337 if(obj.type() == ASN1_Type::Sequence) {
338 BigInt p, a, b, order, cofactor;
339 std::vector<uint8_t> base_pt;
340 std::vector<uint8_t> seed;
341
342 BER_Decoder(bits, len)
343 .start_sequence()
344 .decode_and_check<size_t>(1, "Unknown ECC param version code")
345 .start_sequence()
346 .decode_and_check(OID("1.2.840.10045.1.1"), "Only prime ECC fields supported")
347 .decode(p)
348 .end_cons()
349 .start_sequence()
350 .decode_octet_string_bigint(a)
351 .decode_octet_string_bigint(b)
352 .decode_optional_string(seed, ASN1_Type::BitString, ASN1_Type::BitString)
353 .end_cons()
354 .decode(base_pt, ASN1_Type::OctetString)
355 .decode(order)
356 .decode(cofactor)
357 .end_cons()
358 .verify_end();
359
360 if(p.bits() < 112 || p.bits() > 1024) {
361 throw Decoding_Error("ECC p parameter is invalid size");
362 }
363
364 if(p.is_negative() || !is_bailie_psw_probable_prime(p)) {
365 throw Decoding_Error("ECC p parameter is not a prime");
366 }
367
368 if(a.is_negative() || a >= p) {
369 throw Decoding_Error("Invalid ECC a parameter");
370 }
371
372 if(b <= 0 || b >= p) {
373 throw Decoding_Error("Invalid ECC b parameter");
374 }
375
376 if(order <= 0 || !is_bailie_psw_probable_prime(order)) {
377 throw Decoding_Error("Invalid ECC order parameter");
378 }
379
380 if(cofactor <= 0 || cofactor >= 16) {
381 throw Decoding_Error("Invalid ECC cofactor parameter");
382 }
383
384 std::pair<BigInt, BigInt> base_xy = Botan::OS2ECP(base_pt.data(), base_pt.size(), p, a, b);
385
386 auto data =
387 ec_group_data().lookup_or_create(p, a, b, base_xy.first, base_xy.second, order, cofactor, OID(), source);
388 return std::make_pair(data, true);
389 }
390
391 if(obj.type() == ASN1_Type::Null) {
392 throw Decoding_Error("Cannot handle ImplicitCA ECC parameters");
393 } else {
394 throw Decoding_Error(fmt("Unexpected tag {} while decoding ECC domain params", asn1_tag_to_string(obj.type())));
395 }
396}
397
398EC_Group::EC_Group() = default;
399
400EC_Group::~EC_Group() = default;
401
402EC_Group::EC_Group(const OID& domain_oid) {
403 this->m_data = ec_group_data().lookup(domain_oid);
404 if(!this->m_data) {
405 throw Invalid_Argument("Unknown EC_Group " + domain_oid.to_string());
406 }
407}
408
409EC_Group::EC_Group(std::string_view str) {
410 if(str.empty()) {
411 return; // no initialization / uninitialized
412 }
413
414 try {
415 const OID oid = OID::from_string(str);
416 if(oid.has_value()) {
417 m_data = ec_group_data().lookup(oid);
418 }
419 } catch(...) {}
420
421 if(m_data == nullptr) {
422 if(str.size() > 30 && str.substr(0, 29) == "-----BEGIN EC PARAMETERS-----") {
423 // OK try it as PEM ...
424 secure_vector<uint8_t> ber = PEM_Code::decode_check_label(str, "EC PARAMETERS");
425
426 auto data = BER_decode_EC_group(ber.data(), ber.size(), EC_Group_Source::ExternalSource);
427 this->m_data = data.first;
428 this->m_explicit_encoding = data.second;
429 }
430 }
431
432 if(m_data == nullptr) {
433 throw Invalid_Argument(fmt("Unknown ECC group '{}'", str));
434 }
435}
436
437//static
439 const auto ber = PEM_Code::decode_check_label(pem, "EC PARAMETERS");
440 return EC_Group(ber.data(), ber.size());
441}
442
444 const BigInt& a,
445 const BigInt& b,
446 const BigInt& base_x,
447 const BigInt& base_y,
448 const BigInt& order,
449 const BigInt& cofactor,
450 const OID& oid) {
451 m_data =
452 ec_group_data().lookup_or_create(p, a, b, base_x, base_y, order, cofactor, oid, EC_Group_Source::ExternalSource);
453}
454
455EC_Group::EC_Group(const uint8_t ber[], size_t ber_len) {
456 auto data = BER_decode_EC_group(ber, ber_len, EC_Group_Source::ExternalSource);
457 m_data = data.first;
458 m_explicit_encoding = data.second;
459}
460
461const EC_Group_Data& EC_Group::data() const {
462 if(m_data == nullptr) {
463 throw Invalid_State("EC_Group uninitialized");
464 }
465 return *m_data;
466}
467
469 return data().a_is_minus_3();
470}
471
473 return data().a_is_zero();
474}
475
476size_t EC_Group::get_p_bits() const {
477 return data().p_bits();
478}
479
480size_t EC_Group::get_p_bytes() const {
481 return data().p_bytes();
482}
483
485 return data().order_bits();
486}
487
489 return data().order_bytes();
490}
491
492const BigInt& EC_Group::get_p() const {
493 return data().p();
494}
495
496const BigInt& EC_Group::get_a() const {
497 return data().a();
498}
499
500const BigInt& EC_Group::get_b() const {
501 return data().b();
502}
503
505 return data().base_point();
506}
507
509 return data().order();
510}
511
512const BigInt& EC_Group::get_g_x() const {
513 return data().g_x();
514}
515
516const BigInt& EC_Group::get_g_y() const {
517 return data().g_y();
518}
519
521 return data().cofactor();
522}
523
525 return data().mod_order(k);
526}
527
529 return data().square_mod_order(x);
530}
531
533 return data().multiply_mod_order(x, y);
534}
535
536BigInt EC_Group::multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const {
537 return data().multiply_mod_order(x, y, z);
538}
539
541 return data().inverse_mod_order(x);
542}
543
545 return data().oid();
546}
547
549 return data().source();
550}
551
553 // Hybrid and standard format are (x,y), compressed is y, +1 format byte
554 if(format == EC_Point_Format::Compressed) {
555 return (1 + get_p_bytes());
556 } else {
557 return (1 + 2 * get_p_bytes());
558 }
559}
560
561EC_Point EC_Group::OS2ECP(const uint8_t bits[], size_t len) const {
562 return Botan::OS2ECP(bits, len, data().curve());
563}
564
565EC_Point EC_Group::point(const BigInt& x, const BigInt& y) const {
566 // TODO: randomize the representation?
567 return EC_Point(data().curve(), x, y);
568}
569
570EC_Point EC_Group::point_multiply(const BigInt& x, const EC_Point& pt, const BigInt& y) const {
572 return xy_mul.multi_exp(x, y);
573}
574
577 std::vector<BigInt>& ws) const {
578 return data().blinded_base_point_multiply(k, rng, ws);
579}
580
583 std::vector<BigInt>& ws) const {
584 const EC_Point pt = data().blinded_base_point_multiply(k, rng, ws);
585
586 if(pt.is_zero()) {
587 return BigInt::zero();
588 }
589 return pt.get_affine_x();
590}
591
595
597 const BigInt& k,
599 std::vector<BigInt>& ws) const {
601 // We pass order*cofactor here to "correctly" handle the case where the
602 // point is on the curve but not in the prime order subgroup. This only
603 // matters for groups with cofactor > 1
604 // See https://github.com/randombit/botan/issues/3800
605 return mul.mul(k, rng, get_order() * get_cofactor(), ws);
606}
607
609 return EC_Point(data().curve());
610}
611
612EC_Point EC_Group::hash_to_curve(std::string_view hash_fn,
613 const uint8_t input[],
614 size_t input_len,
615 std::string_view domain,
616 bool random_oracle) const {
617 return this->hash_to_curve(
618 hash_fn, input, input_len, reinterpret_cast<const uint8_t*>(domain.data()), domain.size(), random_oracle);
619}
620
621EC_Point EC_Group::hash_to_curve(std::string_view hash_fn,
622 const uint8_t input[],
623 size_t input_len,
624 const uint8_t domain_sep[],
625 size_t domain_sep_len,
626 bool random_oracle) const {
627#if defined(BOTAN_HAS_EC_HASH_TO_CURVE)
628
629 // Only have SSWU currently
630 if(get_a().is_zero() || get_b().is_zero() || get_p() % 4 == 1) {
631 throw Not_Implemented("EC_Group::hash_to_curve not available for this curve type");
632 }
633
634 return hash_to_curve_sswu(*this, hash_fn, input, input_len, domain_sep, domain_sep_len, random_oracle);
635
636#else
637 BOTAN_UNUSED(hash_fn, random_oracle, input, input_len, domain_sep, domain_sep_len);
638 throw Not_Implemented("EC_Group::hash_to_curve functionality not available in this configuration");
639#endif
640}
641
642std::vector<uint8_t> EC_Group::DER_encode(EC_Group_Encoding form) const {
643 std::vector<uint8_t> output;
644
645 DER_Encoder der(output);
646
647 if(form == EC_Group_Encoding::Explicit) {
648 const size_t ecpVers1 = 1;
649 const OID curve_type("1.2.840.10045.1.1"); // prime field
650
651 const size_t p_bytes = get_p_bytes();
652
653 der.start_sequence()
654 .encode(ecpVers1)
656 .encode(curve_type)
657 .encode(get_p())
658 .end_cons()
662 .end_cons()
664 .encode(get_order())
666 .end_cons();
667 } else if(form == EC_Group_Encoding::NamedCurve) {
668 const OID oid = get_curve_oid();
669 if(oid.empty()) {
670 throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
671 }
672 der.encode(oid);
673 } else if(form == EC_Group_Encoding::ImplicitCA) {
674 der.encode_null();
675 } else {
676 throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
677 }
678
679 return output;
680}
681
682std::string EC_Group::PEM_encode() const {
683 const std::vector<uint8_t> der = DER_encode(EC_Group_Encoding::Explicit);
684 return PEM_Code::encode(der, "EC PARAMETERS");
685}
686
687bool EC_Group::operator==(const EC_Group& other) const {
688 if(m_data == other.m_data) {
689 return true; // same shared rep
690 }
691
692 return (get_p() == other.get_p() && get_a() == other.get_a() && get_b() == other.get_b() &&
693 get_g_x() == other.get_g_x() && get_g_y() == other.get_g_y() && get_order() == other.get_order() &&
694 get_cofactor() == other.get_cofactor());
695}
696
698 //check that public point is not at infinity
699 if(point.is_zero()) {
700 return false;
701 }
702
703 //check that public point is on the curve
704 if(point.on_the_curve() == false) {
705 return false;
706 }
707
708 //check that public point has order q
709 if((point * get_order()).is_zero() == false) {
710 return false;
711 }
712
713 if(get_cofactor() > 1) {
714 if((point * get_cofactor()).is_zero()) {
715 return false;
716 }
717 }
718
719 return true;
720}
721
722bool EC_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
723 const bool is_builtin = source() == EC_Group_Source::Builtin;
724
725 if(is_builtin && !strong) {
726 return true;
727 }
728
729 const BigInt& p = get_p();
730 const BigInt& a = get_a();
731 const BigInt& b = get_b();
732 const BigInt& order = get_order();
733 const EC_Point& base_point = get_base_point();
734
735 if(p <= 3 || order <= 0) {
736 return false;
737 }
738 if(a < 0 || a >= p) {
739 return false;
740 }
741 if(b <= 0 || b >= p) {
742 return false;
743 }
744
745 const size_t test_prob = 128;
746 const bool is_randomly_generated = is_builtin;
747
748 //check if field modulus is prime
749 if(!is_prime(p, rng, test_prob, is_randomly_generated)) {
750 return false;
751 }
752
753 //check if order is prime
754 if(!is_prime(order, rng, test_prob, is_randomly_generated)) {
755 return false;
756 }
757
758 //compute the discriminant: 4*a^3 + 27*b^2 which must be nonzero
759 const Modular_Reducer mod_p(p);
760
761 const BigInt discriminant = mod_p.reduce(mod_p.multiply(4, mod_p.cube(a)) + mod_p.multiply(27, mod_p.square(b)));
762
763 if(discriminant == 0) {
764 return false;
765 }
766
767 //check for valid cofactor
768 if(get_cofactor() < 1) {
769 return false;
770 }
771
772 //check if the base point is on the curve
773 if(!base_point.on_the_curve()) {
774 return false;
775 }
776 if((base_point * get_cofactor()).is_zero()) {
777 return false;
778 }
779 //check if order of the base point is correct
780 if(!(base_point * order).is_zero()) {
781 return false;
782 }
783
784 return true;
785}
786
787} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
static BigInt zero()
Definition bigint.h:45
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition big_rand.cpp:43
static BigInt one()
Definition bigint.h:50
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition big_code.cpp:105
const BigInt & get_a() const
Definition curve_gfp.h:107
const BigInt & get_p() const
Definition curve_gfp.h:118
const BigInt & get_b() const
Definition curve_gfp.h:112
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & encode_null()
Definition der_enc.cpp:243
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
bool a_is_minus_3() const
Definition ec_group.cpp:468
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition ec_group.cpp:581
const BigInt & get_b() const
Definition ec_group.cpp:500
const BigInt & get_a() const
Definition ec_group.cpp:496
const BigInt & get_g_y() const
Definition ec_group.cpp:516
const BigInt & get_cofactor() const
Definition ec_group.cpp:520
BigInt mod_order(const BigInt &x) const
Definition ec_group.cpp:524
bool operator==(const EC_Group &other) const
Definition ec_group.cpp:687
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:532
EC_Point zero_point() const
Definition ec_group.cpp:608
EC_Group_Source source() const
Definition ec_group.cpp:548
bool a_is_zero() const
Definition ec_group.cpp:472
bool verify_public_element(const EC_Point &y) const
Definition ec_group.cpp:697
static EC_Group EC_Group_from_PEM(std::string_view pem)
Definition ec_group.cpp:438
const BigInt & get_p() const
Definition ec_group.cpp:492
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
Definition ec_group.cpp:722
const BigInt & get_order() const
Definition ec_group.cpp:508
size_t get_p_bits() const
Definition ec_group.cpp:476
const EC_Point & get_base_point() const
Definition ec_group.cpp:504
EC_Point point(const BigInt &x, const BigInt &y) const
Definition ec_group.cpp:565
EC_Point blinded_base_point_multiply(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition ec_group.cpp:575
static std::shared_ptr< EC_Group_Data > EC_group_info(const OID &oid)
Definition ec_named.cpp:15
std::string PEM_encode() const
Definition ec_group.cpp:682
const BigInt & get_g_x() const
Definition ec_group.cpp:512
const OID & get_curve_oid() const
Definition ec_group.cpp:544
BigInt square_mod_order(const BigInt &x) const
Definition ec_group.cpp:528
EC_Point blinded_var_point_multiply(const EC_Point &point, const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
Definition ec_group.cpp:596
static size_t clear_registered_curve_data()
Definition ec_group.cpp:301
std::vector< uint8_t > DER_encode(EC_Group_Encoding form) const
Definition ec_group.cpp:642
BigInt inverse_mod_order(const BigInt &x) const
Definition ec_group.cpp:540
EC_Point hash_to_curve(std::string_view hash_fn, const uint8_t input[], size_t input_len, const uint8_t domain_sep[], size_t domain_sep_len, bool random_oracle=true) const
Definition ec_group.cpp:621
size_t point_size(EC_Point_Format format) const
Definition ec_group.cpp:552
size_t get_p_bytes() const
Definition ec_group.cpp:480
EC_Point point_multiply(const BigInt &x, const EC_Point &pt, const BigInt &y) const
Definition ec_group.cpp:570
static OID EC_group_identity_from_order(const BigInt &order)
Definition ec_named.cpp:344
EC_Point OS2ECP(const uint8_t bits[], size_t len) const
Definition ec_group.cpp:561
BigInt random_scalar(RandomNumberGenerator &rng) const
Definition ec_group.cpp:592
size_t get_order_bits() const
Definition ec_group.cpp:484
size_t get_order_bytes() const
Definition ec_group.cpp:488
EC_Point mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
Definition point_mul.cpp:78
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
EC_Point mul(const BigInt &k, RandomNumberGenerator &rng, const BigInt &group_order, std::vector< BigInt > &ws) const
BigInt get_affine_x() const
Definition ec_point.cpp:469
bool is_zero() const
Definition ec_point.h:177
bool on_the_curve() const
Definition ec_point.cpp:510
BigInt cube(const BigInt &x) const
Definition reducer.h:50
BigInt square(const BigInt &x) const
Definition reducer.h:43
BigInt multiply(const BigInt &x, const BigInt &y) const
Definition reducer.h:30
BigInt reduce(const BigInt &x) const
Definition reducer.cpp:37
bool has_value() const
Definition asn1_obj.h:271
bool empty() const
Definition asn1_obj.h:265
std::string to_string() const
Definition asn1_oid.cpp:108
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:74
int(* final)(unsigned char *, CTX *)
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
secure_vector< uint8_t > decode_check_label(DataSource &source, std::string_view label_want)
Definition pem.cpp:49
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition pem.cpp:62
EC_Group_Source
Definition ec_group.h:34
noop_mutex mutex_type
Definition mutex.h:37
std::string asn1_tag_to_string(ASN1_Type type)
Definition asn1_obj.cpp:93
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
secure_vector< T > lock(const std::vector< T > &in)
Definition secmem.h:70
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition numthry.cpp:357
EC_Point hash_to_curve_sswu(const EC_Group &group, std::string_view hash_fn, const uint8_t input[], size_t input_len, const uint8_t domain_sep[], size_t domain_sep_len, bool random_oracle)
Definition ec_h2c.cpp:184
EC_Point_Format
Definition ec_point.h:19
bool is_bailie_psw_probable_prime(const BigInt &n, const Modular_Reducer &mod_n)
Definition primality.cpp:89
EC_Point OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
Definition ec_point.cpp:627
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
EC_Group_Encoding
Definition ec_group.h:24
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition mod_inv.cpp:178