• 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

82.48
/src/lib/pubkey/ecc_key/ecc_key.cpp
1
/*
2
* ECC Key implemenation
3
* (C) 2007 Manuel Hartl, FlexSecure GmbH
4
*          Falko Strenzke, FlexSecure GmbH
5
*     2008-2010 Jack Lloyd
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include <botan/ecc_key.h>
11

12
#include <botan/ber_dec.h>
13
#include <botan/der_enc.h>
14
#include <botan/numthry.h>
15
#include <botan/secmem.h>
16
#include <botan/internal/ec_key_data.h>
17
#include <botan/internal/fmt.h>
18
#include <botan/internal/workfactor.h>
19

20
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
21
   #include <botan/ec_point.h>
22
#endif
23

24
namespace Botan {
25

26
size_t EC_PublicKey::key_length() const {
915✔
27
   return domain().get_p_bits();
915✔
28
}
29

30
size_t EC_PublicKey::estimated_strength() const {
534✔
31
   return ecp_work_factor(key_length());
534✔
32
}
33

34
namespace {
35

36
EC_Group_Encoding default_encoding_for(const EC_Group& group) {
23,025✔
37
   if(group.get_curve_oid().empty()) {
23,025✔
38
      return EC_Group_Encoding::Explicit;
39
   } else {
40
      return EC_Group_Encoding::NamedCurve;
23,009✔
41
   }
42
}
43

44
}  // namespace
45

46
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
47
EC_PublicKey::EC_PublicKey(EC_Group group, const EC_Point& pub_point) {
14✔
48
   auto pt = EC_AffinePoint(group, pub_point);
14✔
49
   m_public_key = std::make_shared<const EC_PublicKey_Data>(std::move(group), std::move(pt));
14✔
50
   m_domain_encoding = default_encoding_for(domain());
14✔
51
}
14✔
52
#endif
53

54
EC_PublicKey::EC_PublicKey(EC_Group group, EC_AffinePoint pub_point) {
12,441✔
55
   m_public_key = std::make_shared<const EC_PublicKey_Data>(std::move(group), std::move(pub_point));
12,441✔
56
   m_domain_encoding = default_encoding_for(domain());
12,441✔
57
}
12,441✔
58

59
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
3,766✔
60
   m_public_key = std::make_shared<const EC_PublicKey_Data>(EC_Group(alg_id.parameters()), key_bits);
7,500✔
61
   m_domain_encoding = default_encoding_for(domain());
3,468✔
62
}
3,766✔
63

64
const EC_Group& EC_PublicKey::domain() const {
56,592✔
65
   BOTAN_STATE_CHECK(m_public_key != nullptr);
56,592✔
66
   return m_public_key->group();
56,592✔
67
}
68

69
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
70
const EC_Point& EC_PublicKey::public_point() const {
7✔
71
   BOTAN_STATE_CHECK(m_public_key != nullptr);
7✔
72
   return m_public_key->legacy_point();
7✔
73
}
74
#endif
75

76
const EC_AffinePoint& EC_PublicKey::_public_ec_point() const {
18,835✔
77
   BOTAN_STATE_CHECK(m_public_key != nullptr);
18,835✔
78
   return m_public_key->public_key();
18,835✔
79
}
80

81
bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const {
106✔
82
   // We already checked when deserializing that the point was on the curve
83
   return domain().verify_group(rng) && !_public_ec_point().is_identity();
106✔
84
}
85

86
AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const {
1,220✔
87
   return AlgorithmIdentifier(object_identifier(), DER_domain());
3,660✔
88
}
89

90
std::vector<uint8_t> EC_PublicKey::raw_public_key_bits() const {
806✔
91
   return _public_ec_point().serialize(point_encoding());
806✔
92
}
93

94
std::vector<uint8_t> EC_PublicKey::public_key_bits() const {
616✔
95
   return raw_public_key_bits();
616✔
96
}
97

98
std::vector<uint8_t> EC_PublicKey::DER_domain() const {
1,228✔
99
   return domain().DER_encode(domain_format());
1,228✔
100
}
101

102
void EC_PublicKey::set_point_encoding(EC_Point_Format enc) {
3✔
103
   if(enc != EC_Point_Format::Compressed && enc != EC_Point_Format::Uncompressed && enc != EC_Point_Format::Hybrid) {
3✔
104
      throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
1✔
105
   }
106

107
   m_point_encoding = enc;
2✔
108
}
2✔
109

110
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) {
×
111
   if(form == EC_Group_Encoding::NamedCurve && domain().get_curve_oid().empty()) {
×
112
      throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID");
×
113
   }
114

115
   m_domain_encoding = form;
×
116
}
×
117

118
const BigInt& EC_PrivateKey::private_value() const {
17✔
119
   BOTAN_STATE_CHECK(m_private_key != nullptr);
17✔
120
   return m_private_key->legacy_bigint();
17✔
121
}
122

123
const EC_Scalar& EC_PrivateKey::_private_key() const {
7,398✔
124
   BOTAN_STATE_CHECK(m_private_key != nullptr);
7,398✔
125
   return m_private_key->private_key();
7,398✔
126
}
127

128
/**
129
* EC_PrivateKey constructor
130
*/
131
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
659✔
132
                             EC_Group ec_group,
133
                             const BigInt& x,
134
                             bool with_modular_inverse) {
659✔
135
   auto scalar = (x.is_zero()) ? EC_Scalar::random(ec_group, rng) : EC_Scalar::from_bigint(ec_group, x);
1,318✔
136
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(scalar));
659✔
137
   m_public_key = m_private_key->public_key(rng, with_modular_inverse);
659✔
138
   m_domain_encoding = default_encoding_for(domain());
659✔
139
}
659✔
140

141
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, EC_Group ec_group, bool with_modular_inverse) {
5,976✔
142
   auto scalar = EC_Scalar::random(ec_group, rng);
5,976✔
143
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(scalar));
5,976✔
144
   m_public_key = m_private_key->public_key(rng, with_modular_inverse);
5,976✔
145
   m_domain_encoding = default_encoding_for(domain());
5,976✔
146
}
5,976✔
147

148
EC_PrivateKey::EC_PrivateKey(EC_Group group, const BigInt& bn_scalar, bool with_modular_inverse) {
×
149
   auto scalar = EC_Scalar::from_bigint(group, bn_scalar);
×
150
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(group), std::move(scalar));
×
151
   m_public_key = m_private_key->public_key(with_modular_inverse);
×
152
   m_domain_encoding = default_encoding_for(domain());
×
153
}
×
154

155
EC_PrivateKey::EC_PrivateKey(EC_Group ec_group, EC_Scalar x, bool with_modular_inverse) {
×
156
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(x));
×
157
   m_public_key = m_private_key->public_key(with_modular_inverse);
×
158
   m_domain_encoding = default_encoding_for(domain());
×
159
}
×
160

161
secure_vector<uint8_t> EC_PrivateKey::raw_private_key_bits() const {
761✔
162
   BOTAN_STATE_CHECK(m_private_key != nullptr);
761✔
163
   return m_private_key->serialize<secure_vector<uint8_t>>();
761✔
164
}
165

166
secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const {
758✔
167
   BOTAN_STATE_CHECK(m_private_key != nullptr && m_public_key != nullptr);
758✔
168

169
   return DER_Encoder()
758✔
170
      .start_sequence()
758✔
171
      .encode(static_cast<size_t>(1))
758✔
172
      .encode(raw_private_key_bits(), ASN1_Type::OctetString)
2,274✔
173
      .start_explicit_context_specific(1)
758✔
174
      .encode(m_public_key->public_key().serialize_uncompressed(), ASN1_Type::BitString)
1,516✔
175
      .end_cons()
758✔
176
      .end_cons()
758✔
177
      .get_contents();
1,516✔
178
}
179

180
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
1,399✔
181
                             std::span<const uint8_t> key_bits,
182
                             bool with_modular_inverse) {
1,399✔
183
   EC_Group group(alg_id.parameters());
1,399✔
184

185
   OID key_parameters;
1,051✔
186
   secure_vector<uint8_t> private_key_bits;
1,051✔
187
   secure_vector<uint8_t> public_key_bits;
1,051✔
188

189
   BER_Decoder(key_bits)
2,087✔
190
      .start_sequence()
1,036✔
191
      .decode_and_check<size_t>(1, "Unknown version code for ECC key")
1,036✔
192
      .decode(private_key_bits, ASN1_Type::OctetString)
1,032✔
193
      .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)
2,068✔
194
      .decode_optional_string(public_key_bits, ASN1_Type::BitString, 1, ASN1_Class::ExplicitContextSpecific)
1,027✔
195
      .end_cons();
1,022✔
196

197
   m_private_key = std::make_shared<EC_PrivateKey_Data>(group, private_key_bits);
1,021✔
198

199
   if(public_key_bits.empty()) {
476✔
200
      m_public_key = m_private_key->public_key(with_modular_inverse);
3✔
201
   } else {
202
      m_public_key = std::make_shared<EC_PublicKey_Data>(group, public_key_bits);
1,048✔
203
   }
204

205
   m_domain_encoding = default_encoding_for(domain());
934✔
206
}
3,618✔
207

208
bool EC_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
52✔
209
   if(!m_private_key) {
52✔
210
      return false;
211
   }
212

213
   return EC_PublicKey::check_key(rng, strong);
52✔
214
}
215

216
const BigInt& EC_PublicKey::get_int_field(std::string_view field) const {
2✔
217
   if(field == "public_x" || field == "public_y") {
2✔
218
      throw Not_Implemented(fmt("EC_PublicKey::get_int_field no longer implements getter for {}", field));
×
219
   } else if(field == "base_x") {
2✔
220
      return this->domain().get_g_x();
×
221
   } else if(field == "base_y") {
2✔
222
      return this->domain().get_g_y();
×
223
   } else if(field == "p") {
2✔
224
      return this->domain().get_p();
×
225
   } else if(field == "a") {
2✔
226
      return this->domain().get_a();
×
227
   } else if(field == "b") {
2✔
228
      return this->domain().get_b();
×
229
   } else if(field == "cofactor") {
2✔
230
      return this->domain().get_cofactor();
×
231
   } else if(field == "order") {
2✔
232
      return this->domain().get_order();
×
233
   } else {
234
      return Public_Key::get_int_field(field);
2✔
235
   }
236
}
237

238
const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const {
10✔
239
   if(field == "x") {
10✔
240
      return this->private_value();
9✔
241
   } else {
242
      return EC_PublicKey::get_int_field(field);
1✔
243
   }
244
}
245

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