Botan 3.13.0
Crypto and TLS for C&
Botan::EC_Group_Data Class Referencefinal

#include <ec_inner_data.h>

Inheritance diagram for Botan::EC_Group_Data:

Public Member Functions

const BigInta () const
bool a_is_minus_3 () const
bool a_is_zero () const
std::unique_ptr< EC_AffinePoint_Dataaffine_add (const EC_AffinePoint_Data &p, const EC_AffinePoint_Data &q) const
std::unique_ptr< EC_AffinePoint_Dataaffine_neg (const EC_AffinePoint_Data &p) const
const BigIntb () const
const BigIntcofactor () const
const std::vector< uint8_t > & der_named_curve () 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)
 EC_Group_Data (const EC_Group_Data &other)=delete
 EC_Group_Data (EC_Group_Data &&other)=delete
EC_Group_Engine engine () const
const BigIntg_x () const
const BigIntg_y () const
std::unique_ptr< EC_Scalar_Datagk_x_mod_order (const EC_Scalar_Data &scalar, RandomNumberGenerator &rng) const
bool has_cofactor () const
bool hash_to_curve_supported (std::string_view hash_fn) const
std::unique_ptr< EC_Mul2Table_Datamake_mul2_table (const EC_AffinePoint_Data &pt) const
std::unique_ptr< EC_AffinePoint_Datamul_px_qy (const EC_AffinePoint_Data &p, const EC_Scalar_Data &x, const EC_AffinePoint_Data &q, const EC_Scalar_Data &y, RandomNumberGenerator &rng) const
const OIDoid () const
EC_Group_Dataoperator= (const EC_Group_Data &other)=delete
EC_Group_Dataoperator= (EC_Group_Data &&other)=delete
const BigIntorder () const
size_t order_bits () const
size_t order_bytes () const
bool order_is_less_than_p () const
const BigIntp () const
size_t p_bits () const
size_t p_bytes () const
size_t p_words () 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
bool params_match (const BigInt &p, const BigInt &a, const BigInt &b, std::span< const uint8_t > base_pt, const BigInt &order, const BigInt &cofactor) const
bool params_match (const EC_Group_Data &other) const
const PCurve::PrimeOrderCurvepcurve () const
std::unique_ptr< EC_AffinePoint_Datapoint_deserialize_compressed (std::span< const uint8_t > bytes) const
std::unique_ptr< EC_AffinePoint_Datapoint_deserialize_uncompressed (std::span< const uint8_t > bytes) const
std::unique_ptr< EC_AffinePoint_Datapoint_g_mul (const EC_Scalar_Data &scalar, RandomNumberGenerator &rng) const
std::unique_ptr< EC_AffinePoint_Datapoint_hash_to_curve_nu (std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
std::unique_ptr< EC_AffinePoint_Datapoint_hash_to_curve_ro (std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep) const
std::unique_ptr< EC_AffinePoint_Datapoint_identity () const
 Return the identity element (aka the point at infinity).
std::unique_ptr< EC_Scalar_Datascalar_deserialize (std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Scalar_Datascalar_from_bigint (const BigInt &bn) const
std::unique_ptr< EC_Scalar_Datascalar_from_bytes_mod_order (std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Scalar_Datascalar_from_bytes_with_trunc (std::span< const uint8_t > bytes) const
std::unique_ptr< EC_Scalar_Datascalar_one () const
std::unique_ptr< EC_Scalar_Datascalar_random (RandomNumberGenerator &rng) const
void set_oid (const OID &oid)
EC_Group_Source source () const
 ~EC_Group_Data ()

Static Public Member Functions

static std::shared_ptr< EC_Group_Datacreate (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)

Detailed Description

Definition at line 127 of file ec_inner_data.h.

Constructor & Destructor Documentation

◆ ~EC_Group_Data()

Botan::EC_Group_Data::~EC_Group_Data ( )
default

◆ EC_Group_Data() [1/3]

Botan::EC_Group_Data::EC_Group_Data ( const EC_Group_Data & other)
delete

◆ EC_Group_Data() [2/3]

Botan::EC_Group_Data::EC_Group_Data ( EC_Group_Data && other)
delete

References EC_Group_Data().

◆ EC_Group_Data() [3/3]

Botan::EC_Group_Data::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 )

Note this constructor should only be called by EC_Group_Data::create.

It is only public to allow use of std::make_shared

Definition at line 31 of file ec_inner_data.cpp.

39 :
40 m_p(p),
41 m_a(a),
42 m_b(b),
43 m_g_x(g_x),
44 m_g_y(g_y),
45 m_order(order),
46 m_cofactor(cofactor),
47#if defined(BOTAN_HAS_LEGACY_EC_POINT)
50 m_monty(m_p, m_mod_field),
51#endif
52 m_oid(oid),
53 m_p_words(p.sig_words()),
54 m_p_bits(p.bits()),
55 m_order_bits(order.bits()),
56 m_order_bytes((m_order_bits + 7) / 8),
57 m_a_is_minus_3(a == p - 3),
58 m_a_is_zero(a.is_zero()),
59 m_has_cofactor(m_cofactor != 1),
60 m_order_is_less_than_p(m_order < p),
61 m_source(source) {
62 // Verify the generator (x, y) satisfies y^2 = x^3 + a*x + b (mod p)
64 const BigInt y2 = mod_p.square(g_y);
65 const BigInt x3_ax_b = mod_p.reduce(mod_p.cube(g_x) + mod_p.multiply(a, g_x) + b);
66 if(y2 != x3_ax_b) {
67 throw Invalid_Argument("EC_Group generator is not on the curve");
68 }
69
70 // TODO(Botan4) we can assume/assert the OID is set
71 if(!m_oid.empty()) {
72 DER_Encoder der(m_der_named_curve);
73 der.encode(m_oid);
74
75 if(const auto name = m_oid.registered_name()) {
76 // returns nullptr if unknown or not supported
78 }
79 if(m_pcurve) {
81 }
82 }
83
84 // Try a generic pcurves instance
85 if(!m_pcurve && !m_has_cofactor) {
87 if(m_pcurve) {
88 m_engine = EC_Group_Engine::Generic;
89 }
90 // possibly still null here, if parameters unsuitable or if the
91 // pcurves_generic module wasn't included in the build
92 }
93
94#if defined(BOTAN_HAS_LEGACY_EC_POINT)
96 m_a_r = m_monty.mul(a, m_monty.R2(), ws);
97 m_b_r = m_monty.mul(b, m_monty.R2(), ws);
98 if(!m_pcurve) {
99 m_engine = EC_Group_Engine::Legacy;
100 }
101#else
102 if(!m_pcurve) {
103 if(m_oid.empty()) {
104 throw Not_Implemented("EC_Group this group is not supported in this build configuration");
105 } else {
106 throw Not_Implemented(
107 fmt("EC_Group the group {} is not supported in this build configuration", oid.to_string()));
108 }
109 }
110#endif
111}
static Barrett_Reduction for_public_modulus(const BigInt &m)
Definition barrett.cpp:33
const BigInt & p() const
const BigInt & g_x() const
const BigInt & a() const
const OID & oid() const
const BigInt & cofactor() const
EC_Group_Source source() const
const BigInt & g_y() const
const BigInt & b() const
const BigInt & order() const
static std::shared_ptr< const PrimeOrderCurve > from_params(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &base_x, const BigInt &base_y, const BigInt &order)
Definition pcurves.cpp:21
static std::shared_ptr< const PrimeOrderCurve > for_named_curve(std::string_view name)
Definition pcurves.cpp:32
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
@ Optimized
Using per curve implementation; fastest available.
Definition ec_group.h:50
@ Generic
A generic implementation that handles many curves in one implementation.
Definition ec_group.h:52
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128

References a(), b(), BOTAN_HAS_LEGACY_EC_POINT, cofactor(), Botan::DER_Encoder::encode(), Botan::fmt(), Botan::PCurve::PrimeOrderCurve::for_named_curve(), Botan::Barrett_Reduction::for_public_modulus(), Botan::PCurve::PrimeOrderCurve::from_params(), g_x(), g_y(), Botan::Generic, Botan::Legacy, oid(), Botan::Optimized, order(), p(), source(), and Botan::BigInt::square().

Member Function Documentation

◆ a()

const BigInt & Botan::EC_Group_Data::a ( ) const
inline

Definition at line 172 of file ec_inner_data.h.

172{ return m_a; }

Referenced by create(), EC_Group_Data(), operator=(), params_match(), params_match(), and params_match().

◆ a_is_minus_3()

bool Botan::EC_Group_Data::a_is_minus_3 ( ) const
inline

Definition at line 212 of file ec_inner_data.h.

212{ return m_a_is_minus_3; }

◆ a_is_zero()

bool Botan::EC_Group_Data::a_is_zero ( ) const
inline

Definition at line 214 of file ec_inner_data.h.

214{ return m_a_is_zero; }

◆ affine_add()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::affine_add ( const EC_AffinePoint_Data & p,
const EC_AffinePoint_Data & q ) const

Definition at line 604 of file ec_inner_data.cpp.

605 {
606 if(m_pcurve) {
607 auto pt = m_pcurve->point_add(EC_AffinePoint_Data_PC::checked_ref(p).value(),
609
610 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
611 } else {
612#if defined(BOTAN_HAS_LEGACY_EC_POINT)
613 auto pt = p.to_legacy_point() + q.to_legacy_point();
614 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
615#else
616 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
617#endif
618 }
619}
static const EC_AffinePoint_Data_PC & checked_ref(const EC_AffinePoint_Data &data)

References Botan::EC_AffinePoint_Data_PC::checked_ref(), and p().

◆ affine_neg()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::affine_neg ( const EC_AffinePoint_Data & p) const

Definition at line 621 of file ec_inner_data.cpp.

621 {
622 if(m_pcurve) {
623 auto pt = m_pcurve->point_negate(EC_AffinePoint_Data_PC::checked_ref(p).value());
624 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), pt);
625 } else {
626#if defined(BOTAN_HAS_LEGACY_EC_POINT)
627 auto pt = p.to_legacy_point();
628 pt.negate(); // negates in place
629 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
630#else
631 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
632#endif
633 }
634}

References Botan::EC_AffinePoint_Data_PC::checked_ref(), and p().

◆ b()

const BigInt & Botan::EC_Group_Data::b ( ) const
inline

Definition at line 174 of file ec_inner_data.h.

174{ return m_b; }

Referenced by create(), EC_Group_Data(), operator=(), params_match(), params_match(), and params_match().

◆ cofactor()

const BigInt & Botan::EC_Group_Data::cofactor ( ) const
inline

Definition at line 178 of file ec_inner_data.h.

178{ return m_cofactor; }

Referenced by create(), EC_Group_Data(), operator=(), params_match(), params_match(), and params_match().

◆ create()

std::shared_ptr< EC_Group_Data > Botan::EC_Group_Data::create ( 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 )
static

Definition at line 113 of file ec_inner_data.cpp.

121 {
122 auto group = std::make_shared<EC_Group_Data>(p, a, b, g_x, g_y, order, cofactor, oid, source);
123
124#if defined(BOTAN_HAS_LEGACY_EC_POINT)
125 group->m_curve = CurveGFp(group.get());
126 group->m_base_point = EC_Point(group->m_curve, g_x, g_y);
127 if(!group->m_pcurve) {
128 group->m_base_mult = std::make_unique<EC_Point_Base_Point_Precompute>(group->m_base_point, group->m_mod_order);
129 }
130#endif
131
132 return group;
133}

References a(), b(), cofactor(), g_x(), g_y(), oid(), order(), p(), and source().

◆ der_named_curve()

const std::vector< uint8_t > & Botan::EC_Group_Data::der_named_curve ( ) const
inline

Definition at line 168 of file ec_inner_data.h.

168{ return m_der_named_curve; }

◆ engine()

EC_Group_Engine Botan::EC_Group_Data::engine ( ) const
inline

Definition at line 218 of file ec_inner_data.h.

218{ return m_engine; }

◆ g_x()

const BigInt & Botan::EC_Group_Data::g_x ( ) const
inline

Definition at line 198 of file ec_inner_data.h.

198{ return m_g_x; }

Referenced by create(), EC_Group_Data(), operator=(), params_match(), params_match(), and params_match().

◆ g_y()

const BigInt & Botan::EC_Group_Data::g_y ( ) const
inline

Definition at line 200 of file ec_inner_data.h.

200{ return m_g_y; }

Referenced by create(), EC_Group_Data(), operator=(), params_match(), params_match(), and params_match().

◆ gk_x_mod_order()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::gk_x_mod_order ( const EC_Scalar_Data & scalar,
RandomNumberGenerator & rng ) const

Definition at line 334 of file ec_inner_data.cpp.

335 {
336 if(m_pcurve) {
337 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
338 auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
339 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), gk_x_mod_order);
340 } else {
341#if defined(BOTAN_HAS_LEGACY_EC_POINT)
342 const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
343 BOTAN_STATE_CHECK(m_base_mult != nullptr);
344 std::vector<BigInt> ws;
345 const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);
346
347 if(pt.is_zero()) {
348 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::zero());
349 } else {
350 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(pt.get_affine_x()));
351 }
352#else
353 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
354#endif
355 }
356}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
static BigInt zero()
Definition bigint.h:50
std::unique_ptr< EC_Scalar_Data > gk_x_mod_order(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng) const
static const EC_Scalar_Data_BN & checked_ref(const EC_Scalar_Data &data)
static const EC_Scalar_Data_PC & checked_ref(const EC_Scalar_Data &data)

References BOTAN_STATE_CHECK, Botan::EC_Scalar_Data_BN::checked_ref(), Botan::EC_Scalar_Data_PC::checked_ref(), gk_x_mod_order(), and Botan::BigInt::zero().

Referenced by gk_x_mod_order().

◆ has_cofactor()

bool Botan::EC_Group_Data::has_cofactor ( ) const
inline

Definition at line 196 of file ec_inner_data.h.

196{ return m_has_cofactor; }

◆ hash_to_curve_supported()

bool Botan::EC_Group_Data::hash_to_curve_supported ( std::string_view hash_fn) const

Return true if point_hash_to_curve_ro/point_hash_to_curve_nu will work for this group when using the specified hash function

Definition at line 486 of file ec_inner_data.cpp.

486 {
487#if defined(BOTAN_HAS_XMD)
488 if(!m_pcurve || !m_pcurve->supports_hash_to_curve()) {
489 return false;
490 }
491
492 // Consistent with h2c_expand_message; XOF based expansion is not implemented
493 if(hash_fn.starts_with("SHAKE")) {
494 return false;
495 }
496
497 auto hash = HashFunction::create(hash_fn);
498 if(hash == nullptr) {
499 return false;
500 }
501
502 // The same hash strength requirement enforced by h2c_expand_message
503 const size_t k = std::min<size_t>((order_bits() + 1) / 2, 256);
504 if(hash->security_level() < k) {
505 return false;
506 }
507
508 // The same requirements enforced by expand_message_xmd
509 return hash->hash_block_size() > 0 && hash->output_length() <= hash->hash_block_size();
510#else
511 BOTAN_UNUSED(hash_fn);
512 return false;
513#endif
514}
#define BOTAN_UNUSED
Definition assert.h:144
size_t order_bits() const
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:111

References BOTAN_UNUSED, Botan::HashFunction::create(), and order_bits().

◆ make_mul2_table()

std::unique_ptr< EC_Mul2Table_Data > Botan::EC_Group_Data::make_mul2_table ( const EC_AffinePoint_Data & pt) const

Definition at line 636 of file ec_inner_data.cpp.

636 {
637 if(m_pcurve) {
638 return std::make_unique<EC_Mul2Table_Data_PC>(h);
639 } else {
640#if defined(BOTAN_HAS_LEGACY_EC_POINT)
641 const EC_AffinePoint_Data_BN g(shared_from_this(), this->base_point());
642 return std::make_unique<EC_Mul2Table_Data_BN>(g, h);
643#else
644 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
645#endif
646 }
647}

◆ mul_px_qy()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::mul_px_qy ( const EC_AffinePoint_Data & p,
const EC_Scalar_Data & x,
const EC_AffinePoint_Data & q,
const EC_Scalar_Data & y,
RandomNumberGenerator & rng ) const

Definition at line 559 of file ec_inner_data.cpp.

563 {
564 if(m_pcurve) {
565 auto pt = m_pcurve->mul_px_qy(EC_AffinePoint_Data_PC::checked_ref(p).value(),
569 rng);
570
571 if(pt) {
572 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(*pt));
573 } else {
574 return nullptr;
575 }
576 } else {
577#if defined(BOTAN_HAS_LEGACY_EC_POINT)
578 std::vector<BigInt> ws;
579 const auto& group = p.group();
580
581 // TODO this could be better!
582 const EC_Point_Var_Point_Precompute p_mul(p.to_legacy_point(), rng, ws);
583 const EC_Point_Var_Point_Precompute q_mul(q.to_legacy_point(), rng, ws);
584
585 const auto order = group->order() * group->cofactor(); // See #3800
586
587 auto px = p_mul.mul(EC_Scalar_Data_BN::checked_ref(x).value(), rng, order, ws);
588 auto qy = q_mul.mul(EC_Scalar_Data_BN::checked_ref(y).value(), rng, order, ws);
589
590 auto px_qy = px + qy;
591
592 if(!px_qy.is_zero()) {
593 px_qy.force_affine();
594 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(px_qy));
595 } else {
596 return nullptr;
597 }
598#else
599 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
600#endif
601 }
602}

References Botan::EC_AffinePoint_Data_PC::checked_ref(), Botan::EC_Scalar_Data_BN::checked_ref(), Botan::EC_Scalar_Data_PC::checked_ref(), Botan::EC_Point_Var_Point_Precompute::mul(), order(), and p().

◆ oid()

const OID & Botan::EC_Group_Data::oid ( ) const
inline

Definition at line 166 of file ec_inner_data.h.

166{ return m_oid; }

Referenced by create(), EC_Group_Data(), operator=(), and set_oid().

◆ operator=() [1/2]

EC_Group_Data & Botan::EC_Group_Data::operator= ( const EC_Group_Data & other)
delete

References EC_Group_Data().

◆ operator=() [2/2]

EC_Group_Data & Botan::EC_Group_Data::operator= ( EC_Group_Data && other)
delete

◆ order()

const BigInt & Botan::EC_Group_Data::order ( ) const
inline

Definition at line 176 of file ec_inner_data.h.

176{ return m_order; }

Referenced by create(), EC_Group_Data(), mul_px_qy(), operator=(), params_match(), params_match(), and params_match().

◆ order_bits()

size_t Botan::EC_Group_Data::order_bits ( ) const
inline

Definition at line 208 of file ec_inner_data.h.

208{ return m_order_bits; }

Referenced by hash_to_curve_supported(), point_hash_to_curve_nu(), point_hash_to_curve_ro(), and scalar_from_bytes_with_trunc().

◆ order_bytes()

size_t Botan::EC_Group_Data::order_bytes ( ) const
inline

Definition at line 210 of file ec_inner_data.h.

210{ return m_order_bytes; }

Referenced by scalar_from_bytes_mod_order().

◆ order_is_less_than_p()

bool Botan::EC_Group_Data::order_is_less_than_p ( ) const
inline

Definition at line 194 of file ec_inner_data.h.

194{ return m_order_is_less_than_p; }

◆ p()

const BigInt & Botan::EC_Group_Data::p ( ) const
inline

Definition at line 170 of file ec_inner_data.h.

170{ return m_p; }

Referenced by affine_add(), affine_neg(), create(), EC_Group_Data(), mul_px_qy(), operator=(), params_match(), params_match(), and params_match().

◆ p_bits()

size_t Botan::EC_Group_Data::p_bits ( ) const
inline

Definition at line 204 of file ec_inner_data.h.

204{ return m_p_bits; }

◆ p_bytes()

size_t Botan::EC_Group_Data::p_bytes ( ) const
inline

Definition at line 206 of file ec_inner_data.h.

206{ return (m_p_bits + 7) / 8; }

Referenced by params_match(), point_deserialize_compressed(), and point_deserialize_uncompressed().

◆ p_words()

size_t Botan::EC_Group_Data::p_words ( ) const
inline

Definition at line 202 of file ec_inner_data.h.

202{ return m_p_words; }

◆ params_match() [1/3]

bool Botan::EC_Group_Data::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

Definition at line 135 of file ec_inner_data.cpp.

141 {
142 if(p != this->p()) {
143 return false;
144 }
145 if(a != this->a()) {
146 return false;
147 }
148 if(b != this->b()) {
149 return false;
150 }
151 if(order != this->order()) {
152 return false;
153 }
154 if(cofactor != this->cofactor()) {
155 return false;
156 }
157 if(g_x != this->g_x()) {
158 return false;
159 }
160 if(g_y != this->g_y()) {
161 return false;
162 }
163
164 return true;
165}

References a(), b(), cofactor(), g_x(), g_y(), order(), and p().

Referenced by params_match().

◆ params_match() [2/3]

bool Botan::EC_Group_Data::params_match ( const BigInt & p,
const BigInt & a,
const BigInt & b,
std::span< const uint8_t > base_pt,
const BigInt & order,
const BigInt & cofactor ) const

Definition at line 167 of file ec_inner_data.cpp.

172 {
173 if(p != this->p()) {
174 return false;
175 }
176 if(a != this->a()) {
177 return false;
178 }
179 if(b != this->b()) {
180 return false;
181 }
182 if(order != this->order()) {
183 return false;
184 }
185 if(cofactor != this->cofactor()) {
186 return false;
187 }
188
189 const size_t field_len = this->p_bytes();
190
191 if(base_pt.size() == 1 + field_len && (base_pt[0] == 0x02 || base_pt[0] == 0x03)) {
192 // compressed
193
194 const auto g_x = m_g_x.serialize(field_len);
195 const auto g_y = m_g_y.is_odd();
196
197 const auto sec1_x = base_pt.subspan(1, field_len);
198 const bool sec1_y = (base_pt[0] == 0x03);
199
200 if(!std::ranges::equal(sec1_x, g_x)) {
201 return false;
202 }
203
204 if(sec1_y != g_y) {
205 return false;
206 }
207
208 return true;
209 } else if(base_pt.size() == 1 + 2 * field_len && base_pt[0] == 0x04) {
210 const auto g_x = m_g_x.serialize(field_len);
211 const auto g_y = m_g_y.serialize(field_len);
212
213 const auto sec1_x = base_pt.subspan(1, field_len);
214 const auto sec1_y = base_pt.subspan(1 + field_len, field_len);
215
216 if(!std::ranges::equal(sec1_x, g_x)) {
217 return false;
218 }
219
220 if(!std::ranges::equal(sec1_y, g_y)) {
221 return false;
222 }
223
224 return true;
225 } else {
226 throw Decoding_Error("Invalid base point encoding in explicit group");
227 }
228}
size_t p_bytes() const

References a(), b(), cofactor(), g_x(), g_y(), order(), p(), and p_bytes().

◆ params_match() [3/3]

bool Botan::EC_Group_Data::params_match ( const EC_Group_Data & other) const

Definition at line 230 of file ec_inner_data.cpp.

230 {
231 return params_match(other.p(), other.a(), other.b(), other.g_x(), other.g_y(), other.order(), other.cofactor());
232}
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

References a(), b(), cofactor(), EC_Group_Data(), g_x(), g_y(), order(), p(), and params_match().

◆ pcurve()

const PCurve::PrimeOrderCurve & Botan::EC_Group_Data::pcurve ( ) const
inline

Definition at line 297 of file ec_inner_data.h.

297 {
298 BOTAN_ASSERT_NONNULL(m_pcurve);
299 return *m_pcurve;
300 }
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114

References BOTAN_ASSERT_NONNULL.

◆ point_deserialize_compressed()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::point_deserialize_compressed ( std::span< const uint8_t > bytes) const

Deserialize a point in the SEC1 compressed format

Returns nullptr if the encoding was not in the compressed format, or if the point is not on the curve

Definition at line 410 of file ec_inner_data.cpp.

410 {
411 if(bytes.size() != 1 + p_bytes() || (bytes[0] != 0x02 && bytes[0] != 0x03)) {
412 return {};
413 }
414
415 if(m_pcurve) {
416 if(auto pt = m_pcurve->deserialize_point_compressed(bytes)) {
417 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
418 } else {
419 return {};
420 }
421 } else {
422#if defined(BOTAN_HAS_LEGACY_EC_POINT)
423 try {
424 auto pt = Botan::OS2ECP(bytes, m_curve);
425 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
426 } catch(...) {
427 return {};
428 }
429#else
430 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
431#endif
432 }
433}
EC_Point OS2ECP(std::span< const uint8_t > data, const CurveGFp &curve)
Definition ec_point.cpp:866

References Botan::OS2ECP(), and p_bytes().

◆ point_deserialize_uncompressed()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::point_deserialize_uncompressed ( std::span< const uint8_t > bytes) const

Deserialize a point in the SEC1 uncompressed format

Returns nullptr if the encoding was not in the uncompressed format, or if the point is not on the curve

Definition at line 384 of file ec_inner_data.cpp.

385 {
386 if(bytes.size() != 1 + 2 * p_bytes() || bytes[0] != 0x04) {
387 return {};
388 }
389
390 if(m_pcurve) {
391 if(auto pt = m_pcurve->deserialize_point_uncompressed(bytes)) {
392 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(*pt));
393 } else {
394 return {};
395 }
396 } else {
397#if defined(BOTAN_HAS_LEGACY_EC_POINT)
398 try {
399 auto pt = Botan::OS2ECP(bytes, m_curve);
400 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
401 } catch(...) {
402 return {};
403 }
404#else
405 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
406#endif
407 }
408}

References Botan::OS2ECP(), and p_bytes().

◆ point_g_mul()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::point_g_mul ( const EC_Scalar_Data & scalar,
RandomNumberGenerator & rng ) const

Definition at line 538 of file ec_inner_data.cpp.

539 {
540 if(m_pcurve) {
541 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
542 auto pt = m_pcurve->point_to_affine(m_pcurve->mul_by_g(k.value(), rng));
543 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
544 } else {
545#if defined(BOTAN_HAS_LEGACY_EC_POINT)
546 const auto& group = scalar.group();
547 const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);
548
549 BOTAN_STATE_CHECK(group->m_base_mult != nullptr);
550 std::vector<BigInt> ws;
551 auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
552 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
553#else
554 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
555#endif
556 }
557}

References BOTAN_STATE_CHECK, Botan::EC_Scalar_Data_BN::checked_ref(), Botan::EC_Scalar_Data_PC::checked_ref(), and Botan::EC_Scalar_Data::group().

◆ point_hash_to_curve_nu()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_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

Definition at line 527 of file ec_inner_data.cpp.

529 {
530 if(m_pcurve && m_pcurve->supports_hash_to_curve()) {
531 auto pt = m_pcurve->hash_to_curve_nu(h2c_expand_message(hash_fn, order_bits(), input, domain_sep));
532 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), std::move(pt));
533 } else {
534 throw Not_Implemented("Hash to curve is not implemented for this curve");
535 }
536}
std::function< void(std::span< uint8_t >)> h2c_expand_message(std::string_view hash_fn, size_t order_bits, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)

References Botan::h2c_expand_message(), and order_bits().

◆ point_hash_to_curve_ro()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_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

Definition at line 516 of file ec_inner_data.cpp.

518 {
519 if(m_pcurve && m_pcurve->supports_hash_to_curve()) {
520 auto pt = m_pcurve->hash_to_curve_ro(h2c_expand_message(hash_fn, order_bits(), input, domain_sep));
521 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_to_affine(pt));
522 } else {
523 throw Not_Implemented("Hash to curve is not implemented for this curve");
524 }
525}

References Botan::h2c_expand_message(), and order_bits().

◆ point_identity()

std::unique_ptr< EC_AffinePoint_Data > Botan::EC_Group_Data::point_identity ( ) const

Return the identity element (aka the point at infinity).

Definition at line 435 of file ec_inner_data.cpp.

435 {
436 if(m_pcurve) {
437 return std::make_unique<EC_AffinePoint_Data_PC>(shared_from_this(), m_pcurve->point_identity());
438 } else {
439#if defined(BOTAN_HAS_LEGACY_EC_POINT)
440 return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), EC_Point(m_curve));
441#else
442 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
443#endif
444 }
445}

◆ scalar_deserialize()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_deserialize ( std::span< const uint8_t > bytes) const

Scalar from bytes

This returns a value only if the bytes represent (in big-endian encoding) an integer that is less than n, where n is the group order. It requires that the fixed length encoding (with zero prefix) be used. It also rejects inputs that encode zero. Thus the accepted range is [1,n)

If the input is rejected then nullptr is returned

Definition at line 358 of file ec_inner_data.cpp.

358 {
359 if(bytes.size() != m_order_bytes) {
360 return nullptr;
361 }
362
363 if(m_pcurve) {
364 if(auto s = m_pcurve->deserialize_scalar(bytes)) {
365 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), *s);
366 } else {
367 return nullptr;
368 }
369 } else {
370#if defined(BOTAN_HAS_LEGACY_EC_POINT)
371 BigInt r(bytes);
372
373 if(r.is_zero() || r >= m_order) {
374 return nullptr;
375 }
376
377 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), std::move(r));
378#else
379 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
380#endif
381 }
382}

References Botan::BigInt::is_zero().

Referenced by scalar_from_bigint().

◆ scalar_from_bigint()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_from_bigint ( const BigInt & bn) const

Scalar from BigInt

This returns a value only if bn is in [1,n) where n is the group order. Otherwise it returns nullptr

Definition at line 318 of file ec_inner_data.cpp.

318 {
319 if(bn <= 0 || bn >= m_order) {
320 return {};
321 }
322
323 if(m_pcurve) {
324 return this->scalar_deserialize(bn.serialize(m_order_bytes));
325 } else {
326#if defined(BOTAN_HAS_LEGACY_EC_POINT)
327 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), bn);
328#else
329 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
330#endif
331 }
332}
std::unique_ptr< EC_Scalar_Data > scalar_deserialize(std::span< const uint8_t > bytes) const

References scalar_deserialize(), and Botan::BigInt::serialize().

◆ scalar_from_bytes_mod_order()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_from_bytes_mod_order ( std::span< const uint8_t > bytes) const

Scalar from bytes with modular reduction

This returns a value only if bytes represents (in big-endian encoding) an integer that is at most the square of the scalar group size. Otherwise it returns nullptr.

Definition at line 273 of file ec_inner_data.cpp.

273 {
274 if(bytes.size() > 2 * order_bytes()) {
275 return {};
276 }
277
278 if(m_pcurve) {
279 if(auto s = m_pcurve->scalar_from_wide_bytes(bytes)) {
280 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), std::move(*s));
281 } else {
282 return {};
283 }
284 } else {
285#if defined(BOTAN_HAS_LEGACY_EC_POINT)
286 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), m_mod_order.reduce(BigInt(bytes)));
287#else
288 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
289#endif
290 }
291}
size_t order_bytes() const

References order_bytes().

Referenced by scalar_from_bytes_with_trunc().

◆ scalar_from_bytes_with_trunc()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_from_bytes_with_trunc ( std::span< const uint8_t > bytes) const

Scalar from bytes with ECDSA style truncation

This should always succeed

Definition at line 243 of file ec_inner_data.cpp.

243 {
244 const size_t bit_length = 8 * bytes.size();
245
246 if(bit_length < order_bits()) {
247 // No shifting required, but might still need to reduce by modulus
248 return this->scalar_from_bytes_mod_order(bytes);
249 } else {
250 const size_t shift = bit_length - order_bits();
251
252 const size_t new_length = bytes.size() - (shift / 8);
253 const size_t bit_shift = shift % 8;
254
255 if(bit_shift == 0) {
256 // Easy case just read different bytes
257 return this->scalar_from_bytes_mod_order(bytes.first(new_length));
258 } else {
259 std::vector<uint8_t> sbytes(new_length);
260
261 uint8_t carry = 0;
262 for(size_t i = 0; i != new_length; ++i) {
263 const uint8_t w = bytes[i];
264 sbytes[i] = (w >> bit_shift) | carry;
265 carry = w << (8 - bit_shift);
266 }
267
268 return this->scalar_from_bytes_mod_order(sbytes);
269 }
270 }
271}
std::unique_ptr< EC_Scalar_Data > scalar_from_bytes_mod_order(std::span< const uint8_t > bytes) const
void carry(int64_t &h0, int64_t &h1)

References Botan::carry(), order_bits(), and scalar_from_bytes_mod_order().

◆ scalar_one()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_one ( ) const

Definition at line 306 of file ec_inner_data.cpp.

306 {
307 if(m_pcurve) {
308 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->scalar_one());
309 } else {
310#if defined(BOTAN_HAS_LEGACY_EC_POINT)
311 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), BigInt::one());
312#else
313 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
314#endif
315 }
316}
static BigInt one()
Definition bigint.h:55

References Botan::BigInt::one().

◆ scalar_random()

std::unique_ptr< EC_Scalar_Data > Botan::EC_Group_Data::scalar_random ( RandomNumberGenerator & rng) const

Return a random scalar

This will be in the range [1,n) where n is the group order

Definition at line 293 of file ec_inner_data.cpp.

293 {
294 if(m_pcurve) {
295 return std::make_unique<EC_Scalar_Data_PC>(shared_from_this(), m_pcurve->random_scalar(rng));
296 } else {
297#if defined(BOTAN_HAS_LEGACY_EC_POINT)
298 return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(),
299 BigInt::random_integer(rng, BigInt::one(), m_order));
300#else
301 throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
302#endif
303 }
304}
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition big_rand.cpp:44

References Botan::BigInt::one(), and Botan::BigInt::random_integer().

◆ set_oid()

void Botan::EC_Group_Data::set_oid ( const OID & oid)

Definition at line 234 of file ec_inner_data.cpp.

234 {
235 BOTAN_ARG_CHECK(!oid.empty(), "OID should be set");
236 BOTAN_STATE_CHECK(m_oid.empty() && m_der_named_curve.empty());
237 m_oid = oid;
238
239 DER_Encoder der(m_der_named_curve);
240 der.encode(m_oid);
241}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33

References BOTAN_ARG_CHECK, BOTAN_STATE_CHECK, Botan::DER_Encoder::encode(), and oid().

◆ source()

EC_Group_Source Botan::EC_Group_Data::source ( ) const
inline

Definition at line 216 of file ec_inner_data.h.

216{ return m_source; }

Referenced by create(), and EC_Group_Data().


The documentation for this class was generated from the following files: