Botan 3.9.0
Crypto and TLS for C&
ec_apoint.cpp
Go to the documentation of this file.
1/*
2* (C) 2024 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/ec_apoint.h>
8
9#include <botan/ec_group.h>
10#include <botan/ec_scalar.h>
11#include <botan/internal/ec_inner_data.h>
12#include <botan/internal/mem_utils.h>
13
14namespace Botan {
15
16EC_AffinePoint::EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point) : m_point(std::move(point)) {
17 BOTAN_ASSERT_NONNULL(m_point);
18}
19
20EC_AffinePoint::EC_AffinePoint(const EC_AffinePoint& other) : m_point(other.inner().clone()) {}
21
22EC_AffinePoint::EC_AffinePoint(EC_AffinePoint&& other) noexcept : m_point(std::move(other.m_point)) {}
23
25 if(this != &other) {
26 m_point = other.inner().clone();
27 }
28 return (*this);
29}
30
32 m_point.swap(other.m_point);
33 return (*this);
34}
35
36EC_AffinePoint::EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes) {
37 m_point = group._data()->point_deserialize(bytes);
38 if(!m_point) {
39 throw Decoding_Error("Failed to deserialize elliptic curve point");
40 }
41}
42
43#if defined(BOTAN_HAS_LEGACY_EC_POINT)
44
45EC_Point EC_AffinePoint::to_legacy_point() const {
46 return m_point->to_legacy_point();
47}
48
49EC_AffinePoint::EC_AffinePoint(const EC_Group& group, const EC_Point& pt) :
50 EC_AffinePoint(group, pt.encode(EC_Point_Format::Uncompressed)) {}
51
52#endif
53
55 if(this == &other) {
56 return true;
57 }
58
59 // We are relying on EC_Group to ensure there is just a single shared_ptr
60 // for any set of group params
61 if(this->_group() != other._group()) {
62 return false;
63 }
64
65 auto a_is_id = this->is_identity();
66 auto b_is_id = other.is_identity();
67
68 if(a_is_id || b_is_id) {
69 return (a_is_id == b_is_id);
70 }
71
72 auto a_xy = this->serialize_uncompressed();
73 auto b_xy = other.serialize_uncompressed();
74 BOTAN_ASSERT_NOMSG(a_xy.size() == b_xy.size());
75
76 return CT::is_equal(a_xy.data(), b_xy.data(), a_xy.size()).as_bool();
77}
78
80 const uint8_t id_encoding[1] = {0};
81 return EC_AffinePoint(group, id_encoding);
82}
83
85 // TODO it would be nice to improve this (pcurves supports returning generator directly)
86 if(auto g = EC_AffinePoint::from_bigint_xy(group, group.get_g_x(), group.get_g_y())) {
87 return *g;
88 } else {
89 throw Internal_Error("EC_AffinePoint::generator curve rejected generator");
90 }
91}
92
93std::optional<EC_AffinePoint> EC_AffinePoint::from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y) {
94 if(x.is_negative() || x >= group.get_p()) {
95 return {};
96 }
97 if(y.is_negative() || y >= group.get_p()) {
98 return {};
99 }
100
101 const size_t fe_bytes = group.get_p_bytes();
102 std::vector<uint8_t> sec1(1 + 2 * fe_bytes);
103 sec1[0] = 0x04;
104 x.serialize_to(std::span{sec1}.subspan(1, fe_bytes));
105 y.serialize_to(std::span{sec1}.last(fe_bytes));
106
107 return EC_AffinePoint::deserialize(group, sec1);
108}
109
111 return inner().field_element_bytes();
112}
113
115 return inner().is_identity();
116}
117
119 std::string_view hash_fn,
120 std::span<const uint8_t> input,
121 std::span<const uint8_t> domain_sep) {
122 auto pt = group._data()->point_hash_to_curve_ro(hash_fn, input, domain_sep);
123 return EC_AffinePoint(std::move(pt));
124}
125
127 std::string_view hash_fn,
128 std::span<const uint8_t> input,
129 std::string_view domain_sep) {
130 return EC_AffinePoint::hash_to_curve_ro(group, hash_fn, input, as_span_of_bytes(domain_sep));
131}
132
134 std::string_view hash_fn,
135 std::span<const uint8_t> input,
136 std::span<const uint8_t> domain_sep) {
137 auto pt = group._data()->point_hash_to_curve_nu(hash_fn, input, domain_sep);
138 return EC_AffinePoint(std::move(pt));
139}
140
142 std::string_view hash_fn,
143 std::span<const uint8_t> input,
144 std::string_view domain_sep) {
145 return EC_AffinePoint::hash_to_curve_nu(group, hash_fn, input, as_span_of_bytes(domain_sep));
146}
147
149
150std::optional<EC_AffinePoint> EC_AffinePoint::deserialize(const EC_Group& group, std::span<const uint8_t> bytes) {
151 if(auto pt = group._data()->point_deserialize(bytes)) {
152 return EC_AffinePoint(std::move(pt));
153 } else {
154 return {};
155 }
156}
157
159 auto pt = scalar._inner().group()->point_g_mul(scalar.inner(), rng);
160 return EC_AffinePoint(std::move(pt));
161}
162
164 return EC_AffinePoint(inner().mul(scalar._inner(), rng));
165}
166
168 return inner().mul_x_only(scalar._inner(), rng);
169}
170
171std::optional<EC_AffinePoint> EC_AffinePoint::mul_px_qy(const EC_AffinePoint& p,
172 const EC_Scalar& x,
173 const EC_AffinePoint& q,
174 const EC_Scalar& y,
176 auto pt = p._inner().group()->mul_px_qy(p._inner(), x._inner(), q._inner(), y._inner(), rng);
177 if(pt) {
178 return EC_AffinePoint(std::move(pt));
179 } else {
180 return {};
181 }
182}
183
185 auto pt = _inner().group()->affine_add(_inner(), q._inner());
186 return EC_AffinePoint(std::move(pt));
187}
188
190 auto pt = this->_inner().group()->affine_neg(this->_inner());
191 return EC_AffinePoint(std::move(pt));
192}
193
194std::vector<uint8_t> EC_AffinePoint::serialize(EC_Point_Format format) const {
195 if(format == EC_Point_Format::Compressed) {
196 return this->serialize_compressed();
197 } else if(format == EC_Point_Format::Uncompressed) {
198 return this->serialize_uncompressed();
199 } else {
200 // The deprecated "hybrid" point encoding
201 // TODO(Botan4) Remove this
202 auto enc = this->serialize_uncompressed();
203 const bool y_is_odd = (enc[enc.size() - 1] & 0x01) == 0x01;
204 enc.front() = y_is_odd ? 0x07 : 0x06;
205 return enc;
206 }
207}
208
209void EC_AffinePoint::serialize_x_to(std::span<uint8_t> bytes) const {
211 m_point->serialize_x_to(bytes);
212}
213
214void EC_AffinePoint::serialize_y_to(std::span<uint8_t> bytes) const {
216 m_point->serialize_y_to(bytes);
217}
218
219void EC_AffinePoint::serialize_xy_to(std::span<uint8_t> bytes) const {
221 m_point->serialize_xy_to(bytes);
222}
223
224void EC_AffinePoint::serialize_compressed_to(std::span<uint8_t> bytes) const {
226 m_point->serialize_compressed_to(bytes);
227}
228
229void EC_AffinePoint::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
231 m_point->serialize_uncompressed_to(bytes);
232}
233
234EC_AffinePoint EC_AffinePoint::_from_inner(std::unique_ptr<EC_AffinePoint_Data> inner) {
235 return EC_AffinePoint(std::move(inner));
236}
237
238const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint::_group() const {
239 return inner().group();
240}
241
242} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
void serialize_to(std::span< uint8_t > out) const
Definition bigint.cpp:399
bool is_negative() const
Definition bigint.h:559
virtual std::unique_ptr< EC_AffinePoint_Data > clone() const =0
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
static EC_AffinePoint hash_to_curve_ro(const EC_Group &group, std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
EC_AffinePoint negate() const
Point negation.
size_t field_element_bytes() const
void serialize_xy_to(std::span< uint8_t > bytes) const
static EC_AffinePoint hash_to_curve_nu(const EC_Group &group, std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
bool is_identity() const
Return true if this point is the identity element.
static EC_AffinePoint identity(const EC_Group &group)
Return the identity element.
Definition ec_apoint.cpp:79
static std::optional< EC_AffinePoint > from_bigint_xy(const EC_Group &group, const BigInt &x, const BigInt &y)
Definition ec_apoint.cpp:93
static std::optional< EC_AffinePoint > mul_px_qy(const EC_AffinePoint &p, const EC_Scalar &x, const EC_AffinePoint &q, const EC_Scalar &y, RandomNumberGenerator &rng)
static EC_AffinePoint g_mul(const EC_Scalar &scalar, RandomNumberGenerator &rng)
Multiply by the group generator returning a complete point.
T serialize_uncompressed() const
Definition ec_apoint.h:203
EC_AffinePoint(const EC_Group &group, std::span< const uint8_t > bytes)
Definition ec_apoint.cpp:36
EC_AffinePoint mul(const EC_Scalar &scalar, RandomNumberGenerator &rng) const
Multiply a point by a scalar returning a complete point.
static EC_AffinePoint _from_inner(std::unique_ptr< EC_AffinePoint_Data > inner)
const std::shared_ptr< const EC_Group_Data > & _group() const
static std::optional< EC_AffinePoint > deserialize(const EC_Group &group, std::span< const uint8_t > bytes)
std::vector< uint8_t > serialize(EC_Point_Format format) const
Return an encoding depending on the requested format.
void serialize_x_to(std::span< uint8_t > bytes) const
T serialize_compressed() const
Definition ec_apoint.h:213
void serialize_compressed_to(std::span< uint8_t > bytes) const
secure_vector< uint8_t > mul_x_only(const EC_Scalar &scalar, RandomNumberGenerator &rng) const
Multiply a point by a scalar, returning the byte encoding of the x coordinate only.
const EC_AffinePoint_Data & _inner() const
Definition ec_apoint.h:263
void serialize_uncompressed_to(std::span< uint8_t > bytes) const
void serialize_y_to(std::span< uint8_t > bytes) const
EC_AffinePoint add(const EC_AffinePoint &q) const
EC_AffinePoint & operator=(const EC_AffinePoint &other)
Definition ec_apoint.cpp:24
bool operator==(const EC_AffinePoint &other) const
Definition ec_apoint.cpp:54
static EC_AffinePoint generator(const EC_Group &group)
Return the standard group generator.
Definition ec_apoint.cpp:84
const BigInt & get_g_y() const
Definition ec_group.cpp:606
const BigInt & get_p() const
Definition ec_group.cpp:550
const BigInt & get_g_x() const
Definition ec_group.cpp:602
const std::shared_ptr< EC_Group_Data > & _data() const
Definition ec_group.h:462
size_t get_p_bytes() const
Definition ec_group.cpp:538
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
const EC_Scalar_Data & _inner() const
Definition ec_scalar.h:244
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:826
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:28
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69