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

randombit / botan / 13125461390

04 Feb 2025 12:12AM UTC coverage: 91.232%. Remained the same
13125461390

Pull #4632

github

web-flow
Merge 29ef25392 into 1f4e5fcd7
Pull Request #4632: Remove pcurves "user interface" API

94174 of 103225 relevant lines covered (91.23%)

11468882.81 hits per line

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

86.99
/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) {
159,229✔
25
   const auto* p = dynamic_cast<const EC_Scalar_Data_PC*>(&data);
159,229✔
26
   if(!p) {
159,229✔
27
      throw Invalid_State("Failed conversion to EC_Scalar_Data_PC");
×
28
   }
29
   return *p;
159,229✔
30
}
31

32
const std::shared_ptr<const EC_Group_Data>& EC_Scalar_Data_PC::group() const {
104,879✔
33
   return m_group;
41,855✔
34
}
35

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

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

44
bool EC_Scalar_Data_PC::is_zero() const {
39,639✔
45
   auto& pcurve = this->group()->pcurve();
39,639✔
46
   return pcurve.scalar_is_zero(m_v);
39,639✔
47
}
48

49
bool EC_Scalar_Data_PC::is_eq(const EC_Scalar_Data& other) const {
1,536✔
50
   auto& pcurve = group()->pcurve();
1,536✔
51
   return pcurve.scalar_equal(m_v, checked_ref(other).m_v);
1,536✔
52
}
53

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

58
void EC_Scalar_Data_PC::square_self() {
3,182✔
59
   // TODO square in place
60
   m_v = m_group->pcurve().scalar_square(m_v);
3,182✔
61
}
3,182✔
62

63
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::negate() const {
7,426✔
64
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_negate(m_v));
7,426✔
65
}
66

67
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert() const {
6,804✔
68
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_invert(m_v));
6,804✔
69
}
70

71
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert_vartime() const {
19,055✔
72
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_invert_vartime(m_v));
19,055✔
73
}
74

75
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::add(const EC_Scalar_Data& other) const {
8,466✔
76
   return std::make_unique<EC_Scalar_Data_PC>(m_group, group()->pcurve().scalar_add(m_v, checked_ref(other).m_v));
8,466✔
77
}
78

79
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::sub(const EC_Scalar_Data& other) const {
6,483✔
80
   return std::make_unique<EC_Scalar_Data_PC>(m_group, group()->pcurve().scalar_sub(m_v, checked_ref(other).m_v));
6,483✔
81
}
82

83
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::mul(const EC_Scalar_Data& other) const {
60,201✔
84
   return std::make_unique<EC_Scalar_Data_PC>(m_group, group()->pcurve().scalar_mul(m_v, checked_ref(other).m_v));
60,201✔
85
}
86

87
void EC_Scalar_Data_PC::serialize_to(std::span<uint8_t> bytes) const {
48,139✔
88
   BOTAN_ARG_CHECK(bytes.size() == m_group->order_bytes(), "Invalid output length");
48,139✔
89
   m_group->pcurve().serialize_scalar(bytes, m_v);
48,139✔
90
}
48,139✔
91

92
EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
71,623✔
93
                                               PCurve::PrimeOrderCurve::AffinePoint pt) :
71,623✔
94
      m_group(std::move(group)), m_pt(std::move(pt)) {
71,623✔
95
   auto& pcurve = m_group->pcurve();
71,623✔
96

97
   if(!pcurve.affine_point_is_identity(m_pt)) {
71,623✔
98
      m_xy.resize(1 + 2 * field_element_bytes());
71,407✔
99
      pcurve.serialize_point(m_xy, m_pt);
71,407✔
100
   }
101
}
71,623✔
102

103
EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
×
104
                                               std::span<const uint8_t> bytes) :
×
105
      m_group(std::move(group)), m_pt(deserialize_pcurve_pt(m_group->pcurve(), bytes)) {
×
106
   auto& pcurve = m_group->pcurve();
×
107

108
   if(!pcurve.affine_point_is_identity(m_pt)) {
×
109
      m_xy.resize(1 + 2 * field_element_bytes());
×
110
      pcurve.serialize_point(m_xy, m_pt);
×
111
   }
112
}
×
113

114
const EC_AffinePoint_Data_PC& EC_AffinePoint_Data_PC::checked_ref(const EC_AffinePoint_Data& data) {
32,777✔
115
   const auto* p = dynamic_cast<const EC_AffinePoint_Data_PC*>(&data);
32,777✔
116
   if(!p) {
32,777✔
117
      throw Invalid_State("Failed conversion to EC_AffinePoint_Data_PC");
×
118
   }
119
   return *p;
32,777✔
120
}
121

122
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::clone() const {
11,701✔
123
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, m_pt);
11,701✔
124
}
125

126
const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_PC::group() const {
49,566✔
127
   return m_group;
49,566✔
128
}
129

130
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::mul(const EC_Scalar_Data& scalar,
10,020✔
131
                                                                 RandomNumberGenerator& rng,
132
                                                                 std::vector<BigInt>& ws) const {
133
   BOTAN_UNUSED(ws);
10,020✔
134

135
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
10,020✔
136
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
10,020✔
137
   auto& pcurve = m_group->pcurve();
10,020✔
138
   auto pt = pcurve.point_to_affine(pcurve.mul(m_pt, k, rng));
10,020✔
139
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, std::move(pt));
10,020✔
140
}
10,020✔
141

142
secure_vector<uint8_t> EC_AffinePoint_Data_PC::mul_x_only(const EC_Scalar_Data& scalar,
2,649✔
143
                                                          RandomNumberGenerator& rng,
144
                                                          std::vector<BigInt>& ws) const {
145
   BOTAN_UNUSED(ws);
2,649✔
146

147
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
2,649✔
148
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
2,649✔
149
   return m_group->pcurve().mul_x_only(m_pt, k, rng);
2,649✔
150
}
151

152
size_t EC_AffinePoint_Data_PC::field_element_bytes() const {
149,519✔
153
   return m_group->pcurve().field_element_bytes();
149,519✔
154
}
155

156
bool EC_AffinePoint_Data_PC::is_identity() const {
80,488✔
157
   return m_xy.empty();
80,488✔
158
}
159

160
void EC_AffinePoint_Data_PC::serialize_x_to(std::span<uint8_t> bytes) const {
8,628✔
161
   BOTAN_STATE_CHECK(!this->is_identity());
8,628✔
162
   const size_t fe_bytes = this->field_element_bytes();
8,628✔
163
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
8,628✔
164
   copy_mem(bytes, std::span{m_xy}.subspan(1, fe_bytes));
8,628✔
165
}
8,628✔
166

167
void EC_AffinePoint_Data_PC::serialize_y_to(std::span<uint8_t> bytes) const {
20✔
168
   BOTAN_STATE_CHECK(!this->is_identity());
20✔
169
   const size_t fe_bytes = this->field_element_bytes();
20✔
170
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
20✔
171
   copy_mem(bytes, std::span{m_xy}.subspan(1 + fe_bytes, fe_bytes));
20✔
172
}
20✔
173

174
void EC_AffinePoint_Data_PC::serialize_xy_to(std::span<uint8_t> bytes) const {
150✔
175
   BOTAN_STATE_CHECK(!this->is_identity());
150✔
176
   const size_t fe_bytes = this->field_element_bytes();
150✔
177
   BOTAN_ARG_CHECK(bytes.size() == 2 * fe_bytes, "Invalid output size");
150✔
178
   copy_mem(bytes, std::span{m_xy}.last(2 * fe_bytes));
150✔
179
}
150✔
180

181
void EC_AffinePoint_Data_PC::serialize_compressed_to(std::span<uint8_t> bytes) const {
8,206✔
182
   BOTAN_STATE_CHECK(!this->is_identity());
8,206✔
183
   const size_t fe_bytes = this->field_element_bytes();
8,206✔
184
   BOTAN_ARG_CHECK(bytes.size() == 1 + fe_bytes, "Invalid output size");
8,206✔
185
   const bool y_is_odd = (m_xy.back() & 0x01) == 0x01;
8,206✔
186

187
   BufferStuffer stuffer(bytes);
8,206✔
188
   stuffer.append(y_is_odd ? 0x03 : 0x02);
12,407✔
189
   this->serialize_x_to(stuffer.next(fe_bytes));
8,206✔
190
}
8,206✔
191

192
void EC_AffinePoint_Data_PC::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
15,287✔
193
   BOTAN_STATE_CHECK(!this->is_identity());
15,287✔
194
   const size_t fe_bytes = this->field_element_bytes();
15,287✔
195
   BOTAN_ARG_CHECK(bytes.size() == 1 + 2 * fe_bytes, "Invalid output size");
15,287✔
196
   copy_mem(bytes, m_xy);
15,287✔
197
}
15,287✔
198

199
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
200
EC_Point EC_AffinePoint_Data_PC::to_legacy_point() const {
21,846✔
201
   if(this->is_identity()) {
21,846✔
202
      return EC_Point(m_group->curve());
96✔
203
   } else {
204
      const size_t fe_bytes = this->field_element_bytes();
21,750✔
205
      return EC_Point(m_group->curve(),
21,750✔
206
                      BigInt::from_bytes(std::span{m_xy}.subspan(1, fe_bytes)),
43,500✔
207
                      BigInt::from_bytes(std::span{m_xy}.last(fe_bytes)));
65,250✔
208
   }
209
}
210
#endif
211

212
EC_Mul2Table_Data_PC::EC_Mul2Table_Data_PC(const EC_AffinePoint_Data& q) : m_group(q.group()) {
11,167✔
213
   BOTAN_ARG_CHECK(q.group() == m_group, "Curve mismatch");
11,167✔
214

215
   const auto& pt_q = EC_AffinePoint_Data_PC::checked_ref(q);
11,167✔
216

217
   m_tbl = m_group->pcurve().mul2_setup_g(pt_q.value());
11,167✔
218
}
11,167✔
219

220
std::unique_ptr<EC_AffinePoint_Data> EC_Mul2Table_Data_PC::mul2_vartime(const EC_Scalar_Data& xd,
1,102✔
221
                                                                        const EC_Scalar_Data& yd) const {
222
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
1,102✔
223

224
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
1,102✔
225
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
1,102✔
226

227
   auto& pcurve = m_group->pcurve();
1,102✔
228

229
   if(auto pt = pcurve.mul2_vartime(*m_tbl, x.value(), y.value())) {
1,102✔
230
      return std::make_unique<EC_AffinePoint_Data_PC>(m_group, pcurve.point_to_affine(*pt));
1,102✔
231
   } else {
232
      return nullptr;
×
233
   }
1,102✔
234
}
235

236
bool EC_Mul2Table_Data_PC::mul2_vartime_x_mod_order_eq(const EC_Scalar_Data& vd,
17,603✔
237
                                                       const EC_Scalar_Data& xd,
238
                                                       const EC_Scalar_Data& yd) const {
239
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
17,603✔
240

241
   const auto& v = EC_Scalar_Data_PC::checked_ref(vd);
17,603✔
242
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
17,603✔
243
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
17,603✔
244

245
   return m_group->pcurve().mul2_vartime_x_mod_order_eq(*m_tbl, v.value(), x.value(), y.value());
17,603✔
246
}
247

248
}  // 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