• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 12661312886

07 Jan 2025 11:55PM UTC coverage: 91.251% (-0.02%) from 91.267%
12661312886

push

github

web-flow
Merge pull request #4518 from randombit/jack/ec-point-cleanups

Move EC_Point and related code to deprecated submodule

93407 of 102363 relevant lines covered (91.25%)

11518305.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/lib/pubkey/ec_group/ec_inner_pc.cpp
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
namespace Botan {
10

11
namespace {
12

13
PCurve::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

24
const EC_Scalar_Data_PC& EC_Scalar_Data_PC::checked_ref(const EC_Scalar_Data& data) {
126,973✔
25
   const auto* p = dynamic_cast<const EC_Scalar_Data_PC*>(&data);
126,973✔
26
   if(!p) {
126,973✔
27
      throw Invalid_State("Failed conversion to EC_Scalar_Data_PC");
×
28
   }
29
   return *p;
126,973✔
30
}
31

32
const std::shared_ptr<const EC_Group_Data>& EC_Scalar_Data_PC::group() const {
98,735✔
33
   return m_group;
40,046✔
34
}
35

36
size_t EC_Scalar_Data_PC::bytes() const {
8,763✔
37
   return this->group()->order_bytes();
8,763✔
38
}
39

40
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::clone() const {
40,046✔
41
   return std::make_unique<EC_Scalar_Data_PC>(this->group(), this->value());
40,046✔
42
}
43

44
bool EC_Scalar_Data_PC::is_zero() const {
39,505✔
45
   return this->value().is_zero();
39,505✔
46
}
47

48
bool EC_Scalar_Data_PC::is_eq(const EC_Scalar_Data& other) const {
×
49
   return (value() == checked_ref(other).value());
×
50
}
51

52
void EC_Scalar_Data_PC::assign(const EC_Scalar_Data& other) {
×
53
   m_v = checked_ref(other).value();
×
54
}
×
55

56
void EC_Scalar_Data_PC::square_self() {
3,186✔
57
   // TODO square in place
58
   m_v = m_v.square();
3,186✔
59
}
3,186✔
60

61
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::negate() const {
2,566✔
62
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v.negate());
2,566✔
63
}
64

65
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert() const {
19,716✔
66
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v.invert());
19,716✔
67
}
68

69
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::add(const EC_Scalar_Data& other) const {
2,036✔
70
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v + checked_ref(other).value());
2,036✔
71
}
72

73
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::sub(const EC_Scalar_Data& other) const {
291✔
74
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v - checked_ref(other).value());
291✔
75
}
76

77
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::mul(const EC_Scalar_Data& other) const {
46,421✔
78
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_v * checked_ref(other).value());
46,421✔
79
}
80

81
void EC_Scalar_Data_PC::serialize_to(std::span<uint8_t> bytes) const {
9,630✔
82
   BOTAN_ARG_CHECK(bytes.size() == m_group->order_bytes(), "Invalid output length");
9,630✔
83
   m_group->pcurve().serialize_scalar(bytes, m_v);
9,630✔
84
}
9,630✔
85

86
EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
72,260✔
87
                                               PCurve::PrimeOrderCurve::AffinePoint pt) :
72,260✔
88
      m_group(std::move(group)), m_pt(std::move(pt)) {
72,260✔
89
   if(!m_pt.is_identity()) {
72,260✔
90
      m_xy = m_pt.serialize<secure_vector<uint8_t>>();
72,104✔
91
      BOTAN_ASSERT_NOMSG(m_xy.size() == 1 + 2 * field_element_bytes());
72,104✔
92
   }
93
}
72,260✔
94

95
EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
×
96
                                               std::span<const uint8_t> bytes) :
×
97
      m_group(std::move(group)), m_pt(deserialize_pcurve_pt(m_group->pcurve(), bytes)) {
×
98
   if(!m_pt.is_identity()) {
×
99
      m_xy = m_pt.serialize<secure_vector<uint8_t>>();
×
100
      BOTAN_ASSERT_NOMSG(m_xy.size() == 1 + 2 * field_element_bytes());
×
101
   }
102
}
×
103

104
const EC_AffinePoint_Data_PC& EC_AffinePoint_Data_PC::checked_ref(const EC_AffinePoint_Data& data) {
38,794✔
105
   const auto* p = dynamic_cast<const EC_AffinePoint_Data_PC*>(&data);
38,794✔
106
   if(!p) {
38,794✔
107
      throw Invalid_State("Failed conversion to EC_AffinePoint_Data_PC");
×
108
   }
109
   return *p;
38,794✔
110
}
111

112
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::clone() const {
11,540✔
113
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, m_pt);
11,540✔
114
}
115

116
const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_PC::group() const {
44,867✔
117
   return m_group;
44,867✔
118
}
119

120
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::mul(const EC_Scalar_Data& scalar,
9,839✔
121
                                                                 RandomNumberGenerator& rng,
122
                                                                 std::vector<BigInt>& ws) const {
123
   BOTAN_UNUSED(ws);
9,839✔
124

125
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
9,839✔
126
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
9,839✔
127
   auto pt = m_group->pcurve().mul(m_pt, k, rng).to_affine();
19,678✔
128
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, std::move(pt));
9,839✔
129
}
9,839✔
130

131
secure_vector<uint8_t> EC_AffinePoint_Data_PC::mul_x_only(const EC_Scalar_Data& scalar,
2,649✔
132
                                                          RandomNumberGenerator& rng,
133
                                                          std::vector<BigInt>& ws) const {
134
   BOTAN_UNUSED(ws);
2,649✔
135

136
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
2,649✔
137
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
2,649✔
138
   return m_group->pcurve().mul_x_only(m_pt, k, rng);
2,649✔
139
}
140

141
size_t EC_AffinePoint_Data_PC::field_element_bytes() const {
130,347✔
142
   return m_group->pcurve().field_element_bytes();
130,347✔
143
}
144

145
bool EC_AffinePoint_Data_PC::is_identity() const {
58,479✔
146
   return m_xy.empty();
58,479✔
147
}
148

149
void EC_AffinePoint_Data_PC::serialize_x_to(std::span<uint8_t> bytes) const {
7,416✔
150
   BOTAN_STATE_CHECK(!this->is_identity());
7,416✔
151
   const size_t fe_bytes = this->field_element_bytes();
7,416✔
152
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
7,416✔
153
   copy_mem(bytes, std::span{m_xy}.subspan(1, fe_bytes));
7,416✔
154
}
7,416✔
155

156
void EC_AffinePoint_Data_PC::serialize_y_to(std::span<uint8_t> bytes) const {
20✔
157
   BOTAN_STATE_CHECK(!this->is_identity());
20✔
158
   const size_t fe_bytes = this->field_element_bytes();
20✔
159
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
20✔
160
   copy_mem(bytes, std::span{m_xy}.subspan(1 + fe_bytes, fe_bytes));
20✔
161
}
20✔
162

163
void EC_AffinePoint_Data_PC::serialize_xy_to(std::span<uint8_t> bytes) const {
150✔
164
   BOTAN_STATE_CHECK(!this->is_identity());
150✔
165
   const size_t fe_bytes = this->field_element_bytes();
150✔
166
   BOTAN_ARG_CHECK(bytes.size() == 2 * fe_bytes, "Invalid output size");
150✔
167
   copy_mem(bytes, std::span{m_xy}.last(2 * fe_bytes));
150✔
168
}
150✔
169

170
void EC_AffinePoint_Data_PC::serialize_compressed_to(std::span<uint8_t> bytes) const {
6,995✔
171
   BOTAN_STATE_CHECK(!this->is_identity());
6,995✔
172
   const size_t fe_bytes = this->field_element_bytes();
6,995✔
173
   BOTAN_ARG_CHECK(bytes.size() == 1 + fe_bytes, "Invalid output size");
6,995✔
174
   const bool y_is_odd = (m_xy.back() & 0x01) == 0x01;
6,995✔
175

176
   BufferStuffer stuffer(bytes);
6,995✔
177
   stuffer.append(y_is_odd ? 0x03 : 0x02);
10,599✔
178
   this->serialize_x_to(stuffer.next(fe_bytes));
6,995✔
179
}
6,995✔
180

181
void EC_AffinePoint_Data_PC::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
7,078✔
182
   BOTAN_STATE_CHECK(!this->is_identity());
7,078✔
183
   const size_t fe_bytes = this->field_element_bytes();
7,078✔
184
   BOTAN_ARG_CHECK(bytes.size() == 1 + 2 * fe_bytes, "Invalid output size");
7,078✔
185
   copy_mem(bytes, m_xy);
7,078✔
186
}
7,078✔
187

188
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
189
EC_Point EC_AffinePoint_Data_PC::to_legacy_point() const {
22,030✔
190
   if(this->is_identity()) {
22,030✔
191
      return EC_Point(m_group->curve());
96✔
192
   } else {
193
      const size_t fe_bytes = this->field_element_bytes();
21,934✔
194
      return EC_Point(m_group->curve(),
21,934✔
195
                      BigInt::from_bytes(std::span{m_xy}.subspan(1, fe_bytes)),
43,868✔
196
                      BigInt::from_bytes(std::span{m_xy}.last(fe_bytes)));
65,802✔
197
   }
198
}
199
#endif
200

201
EC_Mul2Table_Data_PC::EC_Mul2Table_Data_PC(const EC_AffinePoint_Data& g, const EC_AffinePoint_Data& h) :
10,405✔
202
      m_group(g.group()) {
10,405✔
203
   BOTAN_ARG_CHECK(h.group() == m_group, "Curve mismatch");
10,405✔
204

205
   const auto& pt_g = EC_AffinePoint_Data_PC::checked_ref(g);
10,405✔
206
   const auto& pt_h = EC_AffinePoint_Data_PC::checked_ref(h);
10,405✔
207

208
   m_tbl = m_group->pcurve().mul2_setup(pt_g.value(), pt_h.value());
10,405✔
209
}
10,405✔
210

211
std::unique_ptr<EC_AffinePoint_Data> EC_Mul2Table_Data_PC::mul2_vartime(const EC_Scalar_Data& xd,
333✔
212
                                                                        const EC_Scalar_Data& yd) const {
213
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
333✔
214

215
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
333✔
216
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
333✔
217

218
   if(auto pt = m_group->pcurve().mul2_vartime(*m_tbl, x.value(), y.value())) {
333✔
219
      return std::make_unique<EC_AffinePoint_Data_PC>(m_group, pt->to_affine());
333✔
220
   } else {
221
      return nullptr;
×
222
   }
333✔
223
}
224

225
bool EC_Mul2Table_Data_PC::mul2_vartime_x_mod_order_eq(const EC_Scalar_Data& vd,
17,624✔
226
                                                       const EC_Scalar_Data& xd,
227
                                                       const EC_Scalar_Data& yd) const {
228
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
17,624✔
229

230
   const auto& v = EC_Scalar_Data_PC::checked_ref(vd);
17,624✔
231
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
17,624✔
232
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
17,624✔
233

234
   return m_group->pcurve().mul2_vartime_x_mod_order_eq(*m_tbl, v.value(), x.value(), y.value());
17,624✔
235
}
236

237
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc