Botan 3.7.1
Crypto and TLS for C&
ec_inner_pc.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/internal/ec_inner_pc.h>
8
9namespace Botan {
10
11namespace {
12
13PCurve::PrimeOrderCurve::AffinePoint deserialize_pcurve_pt(const PCurve::PrimeOrderCurve& curve,
14 std::span<const uint8_t> bytes) {
15 if(auto pt = curve.deserialize_point(bytes)) {
16 return *pt;
17 } else {
18 throw Decoding_Error("Invalid elliptic curve point encoding");
19 }
20}
21
22} // namespace
23
25 const auto* p = dynamic_cast<const EC_Scalar_Data_PC*>(&data);
26 if(!p) {
27 throw Invalid_State("Failed conversion to EC_Scalar_Data_PC");
28 }
29 return *p;
30}
31
32const std::shared_ptr<const EC_Group_Data>& EC_Scalar_Data_PC::group() const {
33 return m_group;
34}
35
37 return this->group()->order_bytes();
38}
39
40std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::clone() const {
41 return std::make_unique<EC_Scalar_Data_PC>(this->group(), this->value());
42}
43
45 return this->value().is_zero();
46}
47
48bool EC_Scalar_Data_PC::is_eq(const EC_Scalar_Data& other) const {
49 return (value() == checked_ref(other).value());
50}
51
53 m_v = checked_ref(other).value();
54}
55
57 // TODO square in place
58 m_v = m_v.square();
59}
60
61std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::negate() const {
62 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v.negate());
63}
64
65std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert() const {
66 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v.invert());
67}
68
69std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert_vartime() const {
70 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v.invert_vartime());
71}
72
73std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::add(const EC_Scalar_Data& other) const {
74 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v + checked_ref(other).value());
75}
76
77std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::sub(const EC_Scalar_Data& other) const {
78 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v - checked_ref(other).value());
79}
80
81std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::mul(const EC_Scalar_Data& other) const {
82 return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v * checked_ref(other).value());
83}
84
85void EC_Scalar_Data_PC::serialize_to(std::span<uint8_t> bytes) const {
86 BOTAN_ARG_CHECK(bytes.size() == m_group->order_bytes(), "Invalid output length");
87 m_group->pcurve().serialize_scalar(bytes, m_v);
88}
89
90EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
92 m_group(std::move(group)), m_pt(std::move(pt)) {
93 if(!m_pt.is_identity()) {
94 m_xy = m_pt.serialize<secure_vector<uint8_t>>();
95 BOTAN_ASSERT_NOMSG(m_xy.size() == 1 + 2 * field_element_bytes());
96 }
97}
98
99EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
100 std::span<const uint8_t> bytes) :
101 m_group(std::move(group)), m_pt(deserialize_pcurve_pt(m_group->pcurve(), bytes)) {
102 if(!m_pt.is_identity()) {
103 m_xy = m_pt.serialize<secure_vector<uint8_t>>();
104 BOTAN_ASSERT_NOMSG(m_xy.size() == 1 + 2 * field_element_bytes());
105 }
106}
107
109 const auto* p = dynamic_cast<const EC_AffinePoint_Data_PC*>(&data);
110 if(!p) {
111 throw Invalid_State("Failed conversion to EC_AffinePoint_Data_PC");
112 }
113 return *p;
114}
115
116std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::clone() const {
117 return std::make_unique<EC_AffinePoint_Data_PC>(m_group, m_pt);
118}
119
120const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_PC::group() const {
121 return m_group;
122}
123
124std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::mul(const EC_Scalar_Data& scalar,
126 std::vector<BigInt>& ws) const {
127 BOTAN_UNUSED(ws);
128
129 BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
130 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
131 auto pt = m_group->pcurve().mul(m_pt, k, rng).to_affine();
132 return std::make_unique<EC_AffinePoint_Data_PC>(m_group, std::move(pt));
133}
134
137 std::vector<BigInt>& ws) const {
138 BOTAN_UNUSED(ws);
139
140 BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
141 const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
142 return m_group->pcurve().mul_x_only(m_pt, k, rng);
143}
144
146 return m_group->pcurve().field_element_bytes();
147}
148
150 return m_xy.empty();
151}
152
153void EC_AffinePoint_Data_PC::serialize_x_to(std::span<uint8_t> bytes) const {
155 const size_t fe_bytes = this->field_element_bytes();
156 BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
157 copy_mem(bytes, std::span{m_xy}.subspan(1, fe_bytes));
158}
159
160void EC_AffinePoint_Data_PC::serialize_y_to(std::span<uint8_t> bytes) const {
162 const size_t fe_bytes = this->field_element_bytes();
163 BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
164 copy_mem(bytes, std::span{m_xy}.subspan(1 + fe_bytes, fe_bytes));
165}
166
167void EC_AffinePoint_Data_PC::serialize_xy_to(std::span<uint8_t> bytes) const {
169 const size_t fe_bytes = this->field_element_bytes();
170 BOTAN_ARG_CHECK(bytes.size() == 2 * fe_bytes, "Invalid output size");
171 copy_mem(bytes, std::span{m_xy}.last(2 * fe_bytes));
172}
173
174void EC_AffinePoint_Data_PC::serialize_compressed_to(std::span<uint8_t> bytes) const {
176 const size_t fe_bytes = this->field_element_bytes();
177 BOTAN_ARG_CHECK(bytes.size() == 1 + fe_bytes, "Invalid output size");
178 const bool y_is_odd = (m_xy.back() & 0x01) == 0x01;
179
180 BufferStuffer stuffer(bytes);
181 stuffer.append(y_is_odd ? 0x03 : 0x02);
182 this->serialize_x_to(stuffer.next(fe_bytes));
183}
184
185void EC_AffinePoint_Data_PC::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
187 const size_t fe_bytes = this->field_element_bytes();
188 BOTAN_ARG_CHECK(bytes.size() == 1 + 2 * fe_bytes, "Invalid output size");
189 copy_mem(bytes, m_xy);
190}
191
192#if defined(BOTAN_HAS_LEGACY_EC_POINT)
193EC_Point EC_AffinePoint_Data_PC::to_legacy_point() const {
194 if(this->is_identity()) {
195 return EC_Point(m_group->curve());
196 } else {
197 const size_t fe_bytes = this->field_element_bytes();
198 return EC_Point(m_group->curve(),
199 BigInt::from_bytes(std::span{m_xy}.subspan(1, fe_bytes)),
200 BigInt::from_bytes(std::span{m_xy}.last(fe_bytes)));
201 }
202}
203#endif
204
206 BOTAN_ARG_CHECK(q.group() == m_group, "Curve mismatch");
207
208 const auto& pt_q = EC_AffinePoint_Data_PC::checked_ref(q);
209
210 m_tbl = m_group->pcurve().mul2_setup_g(pt_q.value());
211}
212
213std::unique_ptr<EC_AffinePoint_Data> EC_Mul2Table_Data_PC::mul2_vartime(const EC_Scalar_Data& xd,
214 const EC_Scalar_Data& yd) const {
215 BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
216
217 const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
218 const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
219
220 if(auto pt = m_group->pcurve().mul2_vartime(*m_tbl, x.value(), y.value())) {
221 return std::make_unique<EC_AffinePoint_Data_PC>(m_group, pt->to_affine());
222 } else {
223 return nullptr;
224 }
225}
226
228 const EC_Scalar_Data& xd,
229 const EC_Scalar_Data& yd) const {
230 BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
231
232 const auto& v = EC_Scalar_Data_PC::checked_ref(vd);
233 const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
234 const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
235
236 return m_group->pcurve().mul2_vartime_x_mod_order_eq(*m_tbl, v.value(), x.value(), y.value());
237}
238
239} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
static BigInt from_bytes(std::span< const uint8_t > bytes)
Definition bigint.cpp:95
Helper class to ease in-place marshalling of concatenated fixed-length values.
Definition stl_util.h:142
constexpr void append(std::span< const uint8_t > buffer)
Definition stl_util.h:177
constexpr std::span< uint8_t > next(size_t bytes)
Definition stl_util.h:150
size_t field_element_bytes() const override
void serialize_uncompressed_to(std::span< uint8_t > bytes) const override
void serialize_xy_to(std::span< uint8_t > bytes) const override
std::unique_ptr< EC_AffinePoint_Data > mul(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const override
std::unique_ptr< EC_AffinePoint_Data > clone() const override
const std::shared_ptr< const EC_Group_Data > & group() const override
EC_AffinePoint_Data_PC(std::shared_ptr< const EC_Group_Data > group, PCurve::PrimeOrderCurve::AffinePoint pt)
bool is_identity() const override
void serialize_x_to(std::span< uint8_t > bytes) const override
void serialize_y_to(std::span< uint8_t > bytes) const override
secure_vector< uint8_t > mul_x_only(const EC_Scalar_Data &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const override
static const EC_AffinePoint_Data_PC & checked_ref(const EC_AffinePoint_Data &data)
void serialize_compressed_to(std::span< uint8_t > bytes) const override
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
bool mul2_vartime_x_mod_order_eq(const EC_Scalar_Data &v, const EC_Scalar_Data &x, const EC_Scalar_Data &y) const override
EC_Mul2Table_Data_PC(const EC_AffinePoint_Data &q)
std::unique_ptr< EC_AffinePoint_Data > mul2_vartime(const EC_Scalar_Data &x, const EC_Scalar_Data &y) const override
void serialize_to(std::span< uint8_t > bytes) const override
std::unique_ptr< EC_Scalar_Data > invert() const override
void assign(const EC_Scalar_Data &y) override
size_t bytes() const override
static const EC_Scalar_Data_PC & checked_ref(const EC_Scalar_Data &data)
std::unique_ptr< EC_Scalar_Data > sub(const EC_Scalar_Data &other) const override
bool is_eq(const EC_Scalar_Data &y) const override
void square_self() override
std::unique_ptr< EC_Scalar_Data > clone() const override
std::unique_ptr< EC_Scalar_Data > mul(const EC_Scalar_Data &other) const override
const std::shared_ptr< const EC_Group_Data > & group() const override
std::unique_ptr< EC_Scalar_Data > negate() const override
bool is_zero() const override
std::unique_ptr< EC_Scalar_Data > add(const EC_Scalar_Data &other) const override
std::unique_ptr< EC_Scalar_Data > invert_vartime() const override
const auto & value() const
Definition ec_inner_pc.h:51
virtual const std::shared_ptr< const EC_Group_Data > & group() const =0
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:147