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

randombit / botan / 21227550842

21 Jan 2026 10:11PM UTC coverage: 90.091% (-0.3%) from 90.4%
21227550842

push

github

web-flow
Merge pull request #5240 from randombit/jack/coverage-build-speedups

Some changes to reduce time taken by the coverage build

102081 of 113309 relevant lines covered (90.09%)

11632809.03 hits per line

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

92.37
/src/lib/pubkey/ec_group/ec_apoint.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/ec_apoint.h>
8

9
#include <botan/ec_group.h>
10
#include <botan/ec_scalar.h>
11
#include <botan/internal/ec_inner_data.h>
12
#include <botan/internal/mem_utils.h>
13

14
namespace Botan {
15

16
EC_AffinePoint::EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point) : m_point(std::move(point)) {
82,853✔
17
   BOTAN_ASSERT_NONNULL(m_point);
82,853✔
18
}
82,853✔
19

20
EC_AffinePoint::EC_AffinePoint(const EC_AffinePoint& other) : m_point(other.inner().clone()) {}
19,786✔
21

22
EC_AffinePoint::EC_AffinePoint(EC_AffinePoint&& other) noexcept : m_point(std::move(other.m_point)) {}
97,858✔
23

24
EC_AffinePoint& EC_AffinePoint::operator=(const EC_AffinePoint& other) {
×
25
   if(this != &other) {
×
26
      m_point = other.inner().clone();
×
27
   }
28
   return (*this);
×
29
}
30

31
EC_AffinePoint& EC_AffinePoint::operator=(EC_AffinePoint&& other) noexcept {
1,641✔
32
   m_point.swap(other.m_point);
1,641✔
33
   return (*this);
1,641✔
34
}
35

36
EC_AffinePoint::EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes) {
17,488✔
37
   m_point = group._data()->point_deserialize(bytes);
17,488✔
38
   if(!m_point) {
17,488✔
39
      throw Decoding_Error("Failed to deserialize elliptic curve point");
6,263✔
40
   }
41
}
17,488✔
42

43
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
44

45
EC_Point EC_AffinePoint::to_legacy_point() const {
30,818✔
46
   return m_point->to_legacy_point();
30,818✔
47
}
48

49
EC_AffinePoint::EC_AffinePoint(const EC_Group& group, const EC_Point& pt) :
846✔
50
      EC_AffinePoint(group, pt.encode(EC_Point_Format::Uncompressed)) {}
1,692✔
51

52
#endif
53

54
bool EC_AffinePoint::operator==(const EC_AffinePoint& other) const {
1,052✔
55
   if(this == &other) {
1,052✔
56
      return true;
57
   }
58

59
   // We are relying on EC_Group to ensure there is just a single shared_ptr
60
   // for any set of group params
61
   if(this->_group() != other._group()) {
1,052✔
62
      return false;
63
   }
64

65
   auto a_is_id = this->is_identity();
1,052✔
66
   auto b_is_id = other.is_identity();
1,052✔
67

68
   if(a_is_id || b_is_id) {
1,052✔
69
      return (a_is_id == b_is_id);
×
70
   }
71

72
   auto a_xy = this->serialize_uncompressed();
1,052✔
73
   auto b_xy = other.serialize_uncompressed();
1,052✔
74
   BOTAN_ASSERT_NOMSG(a_xy.size() == b_xy.size());
1,052✔
75

76
   return CT::is_equal(a_xy.data(), b_xy.data(), a_xy.size()).as_bool();
1,052✔
77
}
2,104✔
78

79
EC_AffinePoint EC_AffinePoint::identity(const EC_Group& group) {
140✔
80
   const uint8_t id_encoding[1] = {0};
140✔
81
   return EC_AffinePoint(group, id_encoding);
140✔
82
}
83

84
EC_AffinePoint EC_AffinePoint::generator(const EC_Group& group) {
914✔
85
   // TODO it would be nice to improve this (pcurves supports returning generator directly)
86
   if(auto g = EC_AffinePoint::from_bigint_xy(group, group.get_g_x(), group.get_g_y())) {
914✔
87
      return *g;
914✔
88
   } else {
89
      throw Internal_Error("EC_AffinePoint::generator curve rejected generator");
×
90
   }
914✔
91
}
92

93
std::optional<EC_AffinePoint> EC_AffinePoint::from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y) {
13,120✔
94
   if(x.is_negative() || x >= group.get_p()) {
13,120✔
95
      return {};
22✔
96
   }
97
   if(y.is_negative() || y >= group.get_p()) {
13,098✔
98
      return {};
19✔
99
   }
100

101
   const size_t fe_bytes = group.get_p_bytes();
13,079✔
102
   std::vector<uint8_t> sec1(1 + 2 * fe_bytes);
13,079✔
103
   sec1[0] = 0x04;
13,079✔
104
   x.serialize_to(std::span{sec1}.subspan(1, fe_bytes));
13,079✔
105
   y.serialize_to(std::span{sec1}.last(fe_bytes));
13,079✔
106

107
   return EC_AffinePoint::deserialize(group, sec1);
13,079✔
108
}
39,237✔
109

110
size_t EC_AffinePoint::field_element_bytes() const {
44,653✔
111
   return inner().field_element_bytes();
44,653✔
112
}
113

114
bool EC_AffinePoint::is_identity() const {
81,338✔
115
   return inner().is_identity();
81,338✔
116
}
117

118
EC_AffinePoint EC_AffinePoint::hash_to_curve_ro(const EC_Group& group,
20✔
119
                                                std::string_view hash_fn,
120
                                                std::span<const uint8_t> input,
121
                                                std::span<const uint8_t> domain_sep) {
122
   auto pt = group._data()->point_hash_to_curve_ro(hash_fn, input, domain_sep);
20✔
123
   return EC_AffinePoint(std::move(pt));
40✔
124
}
20✔
125

126
EC_AffinePoint EC_AffinePoint::hash_to_curve_ro(const EC_Group& group,
×
127
                                                std::string_view hash_fn,
128
                                                std::span<const uint8_t> input,
129
                                                std::string_view domain_sep) {
130
   return EC_AffinePoint::hash_to_curve_ro(group, hash_fn, input, as_span_of_bytes(domain_sep));
×
131
}
132

133
EC_AffinePoint EC_AffinePoint::hash_to_curve_nu(const EC_Group& group,
23✔
134
                                                std::string_view hash_fn,
135
                                                std::span<const uint8_t> input,
136
                                                std::span<const uint8_t> domain_sep) {
137
   auto pt = group._data()->point_hash_to_curve_nu(hash_fn, input, domain_sep);
23✔
138
   return EC_AffinePoint(std::move(pt));
46✔
139
}
23✔
140

141
EC_AffinePoint EC_AffinePoint::hash_to_curve_nu(const EC_Group& group,
×
142
                                                std::string_view hash_fn,
143
                                                std::span<const uint8_t> input,
144
                                                std::string_view domain_sep) {
145
   return EC_AffinePoint::hash_to_curve_nu(group, hash_fn, input, as_span_of_bytes(domain_sep));
×
146
}
147

148
EC_AffinePoint::~EC_AffinePoint() = default;
211,722✔
149

150
std::optional<EC_AffinePoint> EC_AffinePoint::deserialize(const EC_Group& group, std::span<const uint8_t> bytes) {
30,076✔
151
   if(auto pt = group._data()->point_deserialize(bytes)) {
30,076✔
152
      return EC_AffinePoint(std::move(pt));
59,920✔
153
   } else {
154
      return {};
116✔
155
   }
30,076✔
156
}
157

158
EC_AffinePoint EC_AffinePoint::g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) {
15,613✔
159
   auto pt = scalar._inner().group()->point_g_mul(scalar.inner(), rng);
15,613✔
160
   return EC_AffinePoint(std::move(pt));
31,226✔
161
}
15,613✔
162

163
EC_AffinePoint EC_AffinePoint::mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const {
14,605✔
164
   return EC_AffinePoint(inner().mul(scalar._inner(), rng));
29,210✔
165
}
166

167
secure_vector<uint8_t> EC_AffinePoint::mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const {
5,890✔
168
   return inner().mul_x_only(scalar._inner(), rng);
5,890✔
169
}
170

171
std::optional<EC_AffinePoint> EC_AffinePoint::mul_px_qy(const EC_AffinePoint& p,
3,472✔
172
                                                        const EC_Scalar& x,
173
                                                        const EC_AffinePoint& q,
174
                                                        const EC_Scalar& y,
175
                                                        RandomNumberGenerator& rng) {
176
   auto pt = p._inner().group()->mul_px_qy(p._inner(), x._inner(), q._inner(), y._inner(), rng);
3,472✔
177
   if(pt) {
3,472✔
178
      return EC_AffinePoint(std::move(pt));
6,552✔
179
   } else {
180
      return {};
196✔
181
   }
182
}
3,472✔
183

184
EC_AffinePoint EC_AffinePoint::add(const EC_AffinePoint& q) const {
7,745✔
185
   auto pt = _inner().group()->affine_add(_inner(), q._inner());
7,745✔
186
   return EC_AffinePoint(std::move(pt));
15,488✔
187
}
7,744✔
188

189
EC_AffinePoint EC_AffinePoint::negate() const {
9,512✔
190
   auto pt = this->_inner().group()->affine_neg(this->_inner());
9,512✔
191
   return EC_AffinePoint(std::move(pt));
19,024✔
192
}
9,512✔
193

194
std::vector<uint8_t> EC_AffinePoint::serialize(EC_Point_Format format) const {
8,421✔
195
   if(format == EC_Point_Format::Compressed) {
8,421✔
196
      return this->serialize_compressed();
118✔
197
   } else if(format == EC_Point_Format::Uncompressed) {
8,303✔
198
      return this->serialize_uncompressed();
8,211✔
199
   } else {
200
      // The deprecated "hybrid" point encoding
201
      // TODO(Botan4) Remove this
202
      auto enc = this->serialize_uncompressed();
92✔
203
      const bool y_is_odd = (enc[enc.size() - 1] & 0x01) == 0x01;
92✔
204
      enc.front() = y_is_odd ? 0x07 : 0x06;
170✔
205
      return enc;
92✔
206
   }
92✔
207
}
208

209
void EC_AffinePoint::serialize_x_to(std::span<uint8_t> bytes) const {
617✔
210
   BOTAN_STATE_CHECK(!this->is_identity());
617✔
211
   m_point->serialize_x_to(bytes);
617✔
212
}
617✔
213

214
void EC_AffinePoint::serialize_y_to(std::span<uint8_t> bytes) const {
78✔
215
   BOTAN_STATE_CHECK(!this->is_identity());
78✔
216
   m_point->serialize_y_to(bytes);
78✔
217
}
78✔
218

219
void EC_AffinePoint::serialize_xy_to(std::span<uint8_t> bytes) const {
274✔
220
   BOTAN_STATE_CHECK(!this->is_identity());
274✔
221
   m_point->serialize_xy_to(bytes);
274✔
222
}
274✔
223

224
void EC_AffinePoint::serialize_compressed_to(std::span<uint8_t> bytes) const {
11,962✔
225
   BOTAN_STATE_CHECK(!this->is_identity());
11,962✔
226
   m_point->serialize_compressed_to(bytes);
11,962✔
227
}
11,962✔
228

229
void EC_AffinePoint::serialize_uncompressed_to(std::span<uint8_t> bytes) const {
31,736✔
230
   BOTAN_STATE_CHECK(!this->is_identity());
31,736✔
231
   m_point->serialize_uncompressed_to(bytes);
31,736✔
232
}
31,736✔
233

234
EC_AffinePoint EC_AffinePoint::_from_inner(std::unique_ptr<EC_AffinePoint_Data> inner) {
2,100✔
235
   return EC_AffinePoint(std::move(inner));
4,200✔
236
}
237

238
const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint::_group() const {
17,087✔
239
   return inner().group();
17,087✔
240
}
241

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