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