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

randombit / botan / 21698354930

05 Feb 2026 04:06AM UTC coverage: 90.073% (+0.002%) from 90.071%
21698354930

Pull #5285

github

web-flow
Merge 8ee775e73 into 28378faea
Pull Request #5285: Various header inclusion cleanups

102236 of 113503 relevant lines covered (90.07%)

11458235.6 hits per line

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

95.52
/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
#include <botan/mem_ops.h>
10
#include <botan/internal/stl_util.h>
11

12
namespace Botan {
13

14
const EC_Scalar_Data_PC& EC_Scalar_Data_PC::checked_ref(const EC_Scalar_Data& data) {
255,121✔
15
   const auto* p = dynamic_cast<const EC_Scalar_Data_PC*>(&data);
255,121✔
16
   if(p == nullptr) {
255,121✔
17
      throw Invalid_State("Failed conversion to EC_Scalar_Data_PC");
×
18
   }
19
   return *p;
255,121✔
20
}
21

22
const std::shared_ptr<const EC_Group_Data>& EC_Scalar_Data_PC::group() const {
161,335✔
23
   return m_group;
61,823✔
24
}
25

26
size_t EC_Scalar_Data_PC::bytes() const {
99,514✔
27
   return this->group()->order_bytes();
99,514✔
28
}
29

30
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::clone() const {
61,823✔
31
   return std::make_unique<EC_Scalar_Data_PC>(this->group(), this->value());
61,823✔
32
}
33

34
bool EC_Scalar_Data_PC::is_zero() const {
67,806✔
35
   const auto& pcurve = this->group()->pcurve();
67,806✔
36
   return pcurve.scalar_is_zero(m_v);
67,806✔
37
}
38

39
bool EC_Scalar_Data_PC::is_eq(const EC_Scalar_Data& other) const {
3,072✔
40
   const auto& pcurve = group()->pcurve();
3,072✔
41
   return pcurve.scalar_equal(m_v, checked_ref(other).m_v);
3,072✔
42
}
43

44
void EC_Scalar_Data_PC::assign(const EC_Scalar_Data& other) {
×
45
   m_v = checked_ref(other).value();
×
46
}
×
47

48
void EC_Scalar_Data_PC::zeroize() {
8,109✔
49
   m_v._zeroize();
8,109✔
50
}
8,109✔
51

52
void EC_Scalar_Data_PC::square_self() {
5,617✔
53
   // TODO square in place
54
   m_v = m_group->pcurve().scalar_square(m_v);
5,617✔
55
}
5,617✔
56

57
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::negate() const {
12,707✔
58
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_negate(m_v));
12,707✔
59
}
60

61
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert() const {
14,984✔
62
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_invert(m_v));
14,984✔
63
}
64

65
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::invert_vartime() const {
26,290✔
66
   return std::make_unique<EC_Scalar_Data_PC>(m_group, m_group->pcurve().scalar_invert_vartime(m_v));
26,290✔
67
}
68

69
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::add(const EC_Scalar_Data& other) const {
19,061✔
70
   return std::make_unique<EC_Scalar_Data_PC>(m_group, group()->pcurve().scalar_add(m_v, checked_ref(other).m_v));
19,061✔
71
}
72

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

77
std::unique_ptr<EC_Scalar_Data> EC_Scalar_Data_PC::mul(const EC_Scalar_Data& other) const {
102,339✔
78
   return std::make_unique<EC_Scalar_Data_PC>(m_group, group()->pcurve().scalar_mul(m_v, checked_ref(other).m_v));
102,339✔
79
}
80

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

86
EC_AffinePoint_Data_PC::EC_AffinePoint_Data_PC(std::shared_ptr<const EC_Group_Data> group,
104,596✔
87
                                               PCurve::PrimeOrderCurve::AffinePoint pt) :
104,596✔
88
      m_group(std::move(group)), m_pt(std::move(pt)) {
104,596✔
89
   const auto& pcurve = m_group->pcurve();
104,596✔
90

91
   if(!pcurve.affine_point_is_identity(m_pt)) {
104,596✔
92
      m_xy.resize(1 + 2 * field_element_bytes());
104,068✔
93
      pcurve.serialize_point(m_xy, m_pt);
104,068✔
94
   }
95
}
104,596✔
96

97
const EC_AffinePoint_Data_PC& EC_AffinePoint_Data_PC::checked_ref(const EC_AffinePoint_Data& data) {
43,531✔
98
   const auto* p = dynamic_cast<const EC_AffinePoint_Data_PC*>(&data);
43,531✔
99
   if(p == nullptr) {
43,531✔
100
      throw Invalid_State("Failed conversion to EC_AffinePoint_Data_PC");
×
101
   }
102
   return *p;
43,531✔
103
}
104

105
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::clone() const {
18,902✔
106
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, m_pt);
18,902✔
107
}
108

109
const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_PC::group() const {
64,804✔
110
   return m_group;
64,804✔
111
}
112

113
std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::mul(const EC_Scalar_Data& scalar,
13,109✔
114
                                                                 RandomNumberGenerator& rng) const {
115
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
13,109✔
116
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
13,109✔
117
   const auto& pcurve = m_group->pcurve();
13,109✔
118
   auto pt = pcurve.point_to_affine(pcurve.mul(m_pt, k, rng));
13,109✔
119
   return std::make_unique<EC_AffinePoint_Data_PC>(m_group, std::move(pt));
13,109✔
120
}
13,109✔
121

122
secure_vector<uint8_t> EC_AffinePoint_Data_PC::mul_x_only(const EC_Scalar_Data& scalar,
5,084✔
123
                                                          RandomNumberGenerator& rng) const {
124
   BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
5,084✔
125
   const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
5,084✔
126
   return m_group->pcurve().mul_x_only(m_pt, k, rng);
5,084✔
127
}
128

129
size_t EC_AffinePoint_Data_PC::field_element_bytes() const {
223,263✔
130
   return m_group->pcurve().field_element_bytes();
223,263✔
131
}
132

133
bool EC_AffinePoint_Data_PC::is_identity() const {
154,285✔
134
   return m_xy.empty();
154,285✔
135
}
136

137
void EC_AffinePoint_Data_PC::serialize_x_to(std::span<uint8_t> bytes) const {
11,257✔
138
   BOTAN_STATE_CHECK(!this->is_identity());
11,257✔
139
   const size_t fe_bytes = this->field_element_bytes();
11,257✔
140
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
11,257✔
141
   copy_mem(bytes, std::span{m_xy}.subspan(1, fe_bytes));
11,257✔
142
}
11,257✔
143

144
void EC_AffinePoint_Data_PC::serialize_y_to(std::span<uint8_t> bytes) const {
73✔
145
   BOTAN_STATE_CHECK(!this->is_identity());
73✔
146
   const size_t fe_bytes = this->field_element_bytes();
73✔
147
   BOTAN_ARG_CHECK(bytes.size() == fe_bytes, "Invalid output size");
73✔
148
   copy_mem(bytes, std::span{m_xy}.subspan(1 + fe_bytes, fe_bytes));
73✔
149
}
73✔
150

151
void EC_AffinePoint_Data_PC::serialize_xy_to(std::span<uint8_t> bytes) const {
268✔
152
   BOTAN_STATE_CHECK(!this->is_identity());
268✔
153
   const size_t fe_bytes = this->field_element_bytes();
268✔
154
   BOTAN_ARG_CHECK(bytes.size() == 2 * fe_bytes, "Invalid output size");
268✔
155
   copy_mem(bytes, std::span{m_xy}.last(2 * fe_bytes));
268✔
156
}
268✔
157

158
void EC_AffinePoint_Data_PC::serialize_compressed_to(std::span<uint8_t> bytes) const {
10,656✔
159
   BOTAN_STATE_CHECK(!this->is_identity());
10,656✔
160
   const size_t fe_bytes = this->field_element_bytes();
10,656✔
161
   BOTAN_ARG_CHECK(bytes.size() == 1 + fe_bytes, "Invalid output size");
10,656✔
162
   const bool y_is_odd = (m_xy.back() & 0x01) == 0x01;
10,656✔
163

164
   BufferStuffer stuffer(bytes);
10,656✔
165
   stuffer.append(y_is_odd ? 0x03 : 0x02);
16,058✔
166
   this->serialize_x_to(stuffer.next(fe_bytes));
10,656✔
167
}
10,656✔
168

169
void EC_AffinePoint_Data_PC::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
28,014✔
170
   BOTAN_STATE_CHECK(!this->is_identity());
28,014✔
171
   const size_t fe_bytes = this->field_element_bytes();
28,014✔
172
   BOTAN_ARG_CHECK(bytes.size() == 1 + 2 * fe_bytes, "Invalid output size");
28,014✔
173
   copy_mem(bytes, m_xy);
28,014✔
174
}
28,014✔
175

176
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
177
EC_Point EC_AffinePoint_Data_PC::to_legacy_point() const {
29,545✔
178
   if(this->is_identity()) {
29,545✔
179
      return EC_Point(m_group->curve());
216✔
180
   } else {
181
      const size_t fe_bytes = this->field_element_bytes();
29,329✔
182
      return EC_Point(m_group->curve(),
29,329✔
183
                      BigInt::from_bytes(std::span{m_xy}.subspan(1, fe_bytes)),
58,658✔
184
                      BigInt::from_bytes(std::span{m_xy}.last(fe_bytes)));
87,987✔
185
   }
186
}
187
#endif
188

189
EC_Mul2Table_Data_PC::EC_Mul2Table_Data_PC(const EC_AffinePoint_Data& q) : m_group(q.group()) {
14,683✔
190
   BOTAN_ARG_CHECK(q.group() == m_group, "Curve mismatch");
14,683✔
191

192
   const auto& pt_q = EC_AffinePoint_Data_PC::checked_ref(q);
14,683✔
193

194
   m_tbl = m_group->pcurve().mul2_setup_g(pt_q.value());
14,683✔
195
}
14,683✔
196

197
std::unique_ptr<EC_AffinePoint_Data> EC_Mul2Table_Data_PC::mul2_vartime(const EC_Scalar_Data& xd,
1,845✔
198
                                                                        const EC_Scalar_Data& yd) const {
199
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
1,845✔
200

201
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
1,845✔
202
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
1,845✔
203

204
   const auto& pcurve = m_group->pcurve();
1,845✔
205

206
   if(auto pt = pcurve.mul2_vartime(*m_tbl, x.value(), y.value())) {
1,845✔
207
      return std::make_unique<EC_AffinePoint_Data_PC>(m_group, pcurve.point_to_affine(*pt));
1,845✔
208
   } else {
209
      return nullptr;
×
210
   }
1,845✔
211
}
212

213
bool EC_Mul2Table_Data_PC::mul2_vartime_x_mod_order_eq(const EC_Scalar_Data& vd,
23,354✔
214
                                                       const EC_Scalar_Data& xd,
215
                                                       const EC_Scalar_Data& yd) const {
216
   BOTAN_ARG_CHECK(xd.group() == m_group && yd.group() == m_group, "Curve mismatch");
23,354✔
217

218
   const auto& v = EC_Scalar_Data_PC::checked_ref(vd);
23,354✔
219
   const auto& x = EC_Scalar_Data_PC::checked_ref(xd);
23,354✔
220
   const auto& y = EC_Scalar_Data_PC::checked_ref(yd);
23,354✔
221

222
   return m_group->pcurve().mul2_vartime_x_mod_order_eq(*m_tbl, v.value(), x.value(), y.value());
23,354✔
223
}
224

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