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