Coverage Report

Created: 2024-11-29 06:10

/src/botan/src/lib/pubkey/ecc_key/ecc_key.cpp
Line
Count
Source (jump to first uncovered line)
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/ec_point.h>
15
#include <botan/numthry.h>
16
#include <botan/secmem.h>
17
#include <botan/internal/ec_key_data.h>
18
#include <botan/internal/fmt.h>
19
#include <botan/internal/workfactor.h>
20
21
namespace Botan {
22
23
212
size_t EC_PublicKey::key_length() const {
24
212
   return domain().get_p_bits();
25
212
}
26
27
39
size_t EC_PublicKey::estimated_strength() const {
28
39
   return ecp_work_factor(key_length());
29
39
}
30
31
namespace {
32
33
12.0k
EC_Group_Encoding default_encoding_for(const EC_Group& group) {
34
12.0k
   if(group.get_curve_oid().empty()) {
35
30
      return EC_Group_Encoding::Explicit;
36
11.9k
   } else {
37
11.9k
      return EC_Group_Encoding::NamedCurve;
38
11.9k
   }
39
12.0k
}
40
41
}  // namespace
42
43
173
EC_PublicKey::EC_PublicKey(EC_Group group, const EC_Point& pub_point) {
44
173
   auto pt = EC_AffinePoint(group, pub_point);
45
173
   m_public_key = std::make_shared<const EC_PublicKey_Data>(std::move(group), std::move(pt));
46
173
   m_domain_encoding = default_encoding_for(domain());
47
173
}
48
49
0
EC_PublicKey::EC_PublicKey(EC_Group group, EC_AffinePoint pub_point) {
50
0
   m_public_key = std::make_shared<const EC_PublicKey_Data>(std::move(group), std::move(pub_point));
51
0
   m_domain_encoding = default_encoding_for(domain());
52
0
}
53
54
1.48k
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
55
1.48k
   m_public_key = std::make_shared<const EC_PublicKey_Data>(EC_Group(alg_id.parameters()), key_bits);
56
1.48k
   m_domain_encoding = default_encoding_for(domain());
57
1.48k
}
58
59
13.9k
const EC_Group& EC_PublicKey::domain() const {
60
13.9k
   BOTAN_STATE_CHECK(m_public_key != nullptr);
61
13.9k
   return m_public_key->group();
62
13.9k
}
63
64
11.3k
const EC_Point& EC_PublicKey::public_point() const {
65
11.3k
   BOTAN_STATE_CHECK(m_public_key != nullptr);
66
11.3k
   return m_public_key->legacy_point();
67
11.3k
}
68
69
773
const EC_AffinePoint& EC_PublicKey::_public_key() const {
70
773
   BOTAN_STATE_CHECK(m_public_key != nullptr);
71
773
   return m_public_key->public_key();
72
773
}
73
74
0
bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const {
75
0
   return domain().verify_group(rng) && domain().verify_public_element(public_point());
76
0
}
77
78
0
AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const {
79
0
   return AlgorithmIdentifier(object_identifier(), DER_domain());
80
0
}
81
82
173
std::vector<uint8_t> EC_PublicKey::raw_public_key_bits() const {
83
173
   return public_point().encode(point_encoding());
84
173
}
85
86
0
std::vector<uint8_t> EC_PublicKey::public_key_bits() const {
87
0
   return raw_public_key_bits();
88
0
}
89
90
0
std::vector<uint8_t> EC_PublicKey::DER_domain() const {
91
0
   return domain().DER_encode(domain_format());
92
0
}
93
94
0
void EC_PublicKey::set_point_encoding(EC_Point_Format enc) {
95
0
   if(enc != EC_Point_Format::Compressed && enc != EC_Point_Format::Uncompressed && enc != EC_Point_Format::Hybrid) {
96
0
      throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
97
0
   }
98
99
0
   m_point_encoding = enc;
100
0
}
101
102
0
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) {
103
0
   if(form == EC_Group_Encoding::NamedCurve && domain().get_curve_oid().empty()) {
104
0
      throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID");
105
0
   }
106
107
0
   m_domain_encoding = form;
108
0
}
109
110
0
const BigInt& EC_PrivateKey::private_value() const {
111
0
   BOTAN_STATE_CHECK(m_private_key != nullptr);
112
0
   return m_private_key->legacy_bigint();
113
0
}
114
115
173
const EC_Scalar& EC_PrivateKey::_private_key() const {
116
173
   BOTAN_STATE_CHECK(m_private_key != nullptr);
117
173
   return m_private_key->private_key();
118
173
}
119
120
/**
121
* EC_PrivateKey constructor
122
*/
123
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
124
                             EC_Group ec_group,
125
                             const BigInt& x,
126
0
                             bool with_modular_inverse) {
127
0
   auto scalar = (x.is_zero()) ? EC_Scalar::random(ec_group, rng) : EC_Scalar::from_bigint(ec_group, x);
128
0
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(scalar));
129
0
   m_public_key = m_private_key->public_key(rng, with_modular_inverse);
130
0
   m_domain_encoding = default_encoding_for(domain());
131
0
}
132
133
11.0k
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, EC_Group ec_group, bool with_modular_inverse) {
134
11.0k
   auto scalar = EC_Scalar::random(ec_group, rng);
135
11.0k
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(scalar));
136
11.0k
   m_public_key = m_private_key->public_key(rng, with_modular_inverse);
137
11.0k
   m_domain_encoding = default_encoding_for(domain());
138
11.0k
}
139
140
0
EC_PrivateKey::EC_PrivateKey(EC_Group group, const BigInt& bn_scalar, bool with_modular_inverse) {
141
0
   auto scalar = EC_Scalar::from_bigint(group, bn_scalar);
142
0
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(group), std::move(scalar));
143
0
   m_public_key = m_private_key->public_key(with_modular_inverse);
144
0
   m_domain_encoding = default_encoding_for(domain());
145
0
}
146
147
0
EC_PrivateKey::EC_PrivateKey(EC_Group ec_group, EC_Scalar x, bool with_modular_inverse) {
148
0
   m_private_key = std::make_shared<EC_PrivateKey_Data>(std::move(ec_group), std::move(x));
149
0
   m_public_key = m_private_key->public_key(with_modular_inverse);
150
0
   m_domain_encoding = default_encoding_for(domain());
151
0
}
152
153
0
secure_vector<uint8_t> EC_PrivateKey::raw_private_key_bits() const {
154
0
   BOTAN_STATE_CHECK(m_private_key != nullptr);
155
0
   return m_private_key->serialize<secure_vector<uint8_t>>();
156
0
}
157
158
0
secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const {
159
0
   BOTAN_STATE_CHECK(m_private_key != nullptr && m_public_key != nullptr);
160
161
0
   return DER_Encoder()
162
0
      .start_sequence()
163
0
      .encode(static_cast<size_t>(1))
164
0
      .encode(raw_private_key_bits(), ASN1_Type::OctetString)
165
0
      .start_explicit_context_specific(1)
166
0
      .encode(m_public_key->public_key().serialize_uncompressed(), ASN1_Type::BitString)
167
0
      .end_cons()
168
0
      .end_cons()
169
0
      .get_contents();
170
0
}
171
172
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
173
                             std::span<const uint8_t> key_bits,
174
1.56k
                             bool with_modular_inverse) {
175
1.56k
   EC_Group group(alg_id.parameters());
176
177
1.56k
   OID key_parameters;
178
1.56k
   secure_vector<uint8_t> private_key_bits;
179
1.56k
   secure_vector<uint8_t> public_key_bits;
180
181
1.56k
   BER_Decoder(key_bits)
182
1.56k
      .start_sequence()
183
1.56k
      .decode_and_check<size_t>(1, "Unknown version code for ECC key")
184
1.56k
      .decode(private_key_bits, ASN1_Type::OctetString)
185
1.56k
      .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)
186
1.56k
      .decode_optional_string(public_key_bits, ASN1_Type::BitString, 1, ASN1_Class::ExplicitContextSpecific)
187
1.56k
      .end_cons();
188
189
1.56k
   m_private_key = std::make_shared<EC_PrivateKey_Data>(group, private_key_bits);
190
191
1.56k
   if(public_key_bits.empty()) {
192
139
      m_public_key = m_private_key->public_key(with_modular_inverse);
193
1.42k
   } else {
194
1.42k
      m_public_key = std::make_shared<EC_PublicKey_Data>(group, public_key_bits);
195
1.42k
   }
196
197
1.56k
   m_domain_encoding = default_encoding_for(domain());
198
1.56k
}
199
200
0
bool EC_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
201
0
   if(!m_private_key) {
202
0
      return false;
203
0
   }
204
205
0
   return EC_PublicKey::check_key(rng, strong);
206
0
}
207
208
0
const BigInt& EC_PublicKey::get_int_field(std::string_view field) const {
209
0
   if(field == "public_x" || field == "public_y") {
210
0
      throw Not_Implemented(fmt("EC_PublicKey::get_int_field no longer implements getter for {}", field));
211
0
   } else if(field == "base_x") {
212
0
      return this->domain().get_g_x();
213
0
   } else if(field == "base_y") {
214
0
      return this->domain().get_g_y();
215
0
   } else if(field == "p") {
216
0
      return this->domain().get_p();
217
0
   } else if(field == "a") {
218
0
      return this->domain().get_a();
219
0
   } else if(field == "b") {
220
0
      return this->domain().get_b();
221
0
   } else if(field == "cofactor") {
222
0
      return this->domain().get_cofactor();
223
0
   } else if(field == "order") {
224
0
      return this->domain().get_order();
225
0
   } else {
226
0
      return Public_Key::get_int_field(field);
227
0
   }
228
0
}
229
230
0
const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const {
231
0
   if(field == "x") {
232
0
      return this->private_value();
233
0
   } else {
234
0
      return EC_PublicKey::get_int_field(field);
235
0
   }
236
0
}
237
238
}  // namespace Botan