Botan 3.13.0
Crypto and TLS for C&
ecc_key.cpp
Go to the documentation of this file.
1/*
2* ECC Key implementation
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/assert.h>
13#include <botan/ber_dec.h>
14#include <botan/der_enc.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#include <memory>
21
22#if defined(BOTAN_HAS_LEGACY_EC_POINT)
23 #include <botan/ec_point.h>
24#endif
25
26namespace Botan {
27
29 return domain().get_p_bits();
30}
31
35
36namespace {
37
38EC_Group_Encoding default_encoding_for(const EC_Group& group) {
39 if(group.get_curve_oid().empty()) {
41 } else {
43 }
44}
45
46} // namespace
47
49 std::string_view alg_name) {
50 if(alg_id.oid() != OID::from_string(alg_name)) {
51 throw Decoding_Error(
52 fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), alg_name));
53 }
54
55 return alg_id; // NOLINT(*-return-const-ref-from-parameter)
56}
57
58#if defined(BOTAN_HAS_LEGACY_EC_POINT)
59EC_PublicKey::EC_PublicKey(const EC_Group& group, const EC_Point& pub_point) {
60 auto pt = EC_AffinePoint(group, pub_point);
61 m_public_key = std::make_shared<const EC_PublicKey_Data>(group, std::move(pt));
62 m_domain_encoding = default_encoding_for(domain()); // NOLINT(*-prefer-member-initializer)
63}
64#endif
65
66EC_PublicKey::EC_PublicKey(const EC_Group& group, const EC_AffinePoint& pub_point) {
67 m_public_key = std::make_shared<const EC_PublicKey_Data>(group, pub_point);
68 m_domain_encoding = default_encoding_for(domain()); // NOLINT(*-prefer-member-initializer)
69}
70
71EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
72 m_public_key = std::make_shared<const EC_PublicKey_Data>(EC_Group(alg_id.parameters()), key_bits);
73 m_domain_encoding = default_encoding_for(domain()); // NOLINT(*-prefer-member-initializer)
74}
75
78 return m_public_key->group();
79}
80
81#if defined(BOTAN_HAS_LEGACY_EC_POINT)
82const EC_Point& EC_PublicKey::public_point() const {
84 return m_public_key->legacy_point();
85}
86#endif
87
90 return m_public_key->public_key();
91}
92
93bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const {
94 // We already checked when deserializing that the point was on the curve
95 return domain().verify_group(rng) && !_public_ec_point().is_identity();
96}
97
101
102std::vector<uint8_t> EC_PublicKey::raw_public_key_bits() const {
104}
105
106std::vector<uint8_t> EC_PublicKey::public_key_bits() const {
107 return raw_public_key_bits();
108}
109
110std::vector<uint8_t> EC_PublicKey::DER_domain() const {
111 return domain().DER_encode(domain_format());
112}
113
116 throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
117 }
118
119 m_point_encoding = enc;
120}
121
123 if(form == EC_Group_Encoding::NamedCurve && domain().get_curve_oid().empty()) {
124 throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID");
125 }
126
127 m_domain_encoding = form;
128}
129
132 return m_private_key->legacy_bigint();
133}
134
137 return m_private_key->private_key();
138}
139
140/**
141* EC_PrivateKey constructor
142*/
144 const EC_Group& ec_group,
145 const BigInt& x,
146 bool with_modular_inverse) :
147 m_with_modular_inverse(with_modular_inverse) {
148 auto scalar = (x.is_zero()) ? EC_Scalar::random(ec_group, rng) : EC_Scalar::from_bigint(ec_group, x);
149 m_private_key = std::make_shared<EC_PrivateKey_Data>(ec_group, std::move(scalar));
150 m_public_key = m_private_key->public_key(rng, with_modular_inverse);
151 m_domain_encoding = default_encoding_for(domain());
152}
153
154EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, const EC_Group& ec_group, bool with_modular_inverse) :
155 m_with_modular_inverse(with_modular_inverse) {
156 auto scalar = EC_Scalar::random(ec_group, rng);
157 m_private_key = std::make_shared<EC_PrivateKey_Data>(ec_group, std::move(scalar));
158 m_public_key = m_private_key->public_key(rng, with_modular_inverse);
159 m_domain_encoding = default_encoding_for(domain());
160}
161
162EC_PrivateKey::EC_PrivateKey(const EC_Group& ec_group, const EC_Scalar& x, bool with_modular_inverse) :
163 m_with_modular_inverse(with_modular_inverse) {
164 m_private_key = std::make_shared<EC_PrivateKey_Data>(ec_group, x);
165 m_public_key = m_private_key->public_key(with_modular_inverse);
166 m_domain_encoding = default_encoding_for(domain());
167}
168
173
175 BOTAN_STATE_CHECK(m_private_key != nullptr && m_public_key != nullptr);
176
177 return DER_Encoder()
179 .encode(static_cast<size_t>(1))
182 .encode_octet_aligned_bitstring(m_public_key->public_key().serialize_uncompressed())
183 .end_cons()
184 .end_cons()
185 .get_contents();
186}
187
189 std::span<const uint8_t> key_bits,
190 bool with_modular_inverse) :
191 m_with_modular_inverse(with_modular_inverse) {
192 OID key_parameters;
195
198 .decode_and_check<size_t>(1, "Unknown version code for ECC key")
200 .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)
201 .decode_optional_octet_aligned_bitstring(public_key_bits, 1, ASN1_Class::ExplicitContextSpecific)
202 .end_cons()
203 .verify_end();
204
205 std::unique_ptr<EC_Group> group;
206
207 if(!alg_id.parameters_are_empty()) {
208 group = std::make_unique<EC_Group>(alg_id.parameters());
209 }
210 if(!key_parameters.empty()) {
211 if(group) {
212 if(EC_Group(key_parameters) != *group) {
213 throw Invalid_Argument(
214 "Domain parameters supplied AlgorithmIdentifier does not match the ECC private key's domain parameters in EC_PrivateKey construction");
215 }
216 } else {
217 group = std::make_unique<EC_Group>(key_parameters);
218 }
219 }
220 if(!group) {
221 throw Invalid_Argument("Domain parameters are not supplied in EC_PrivateKey construction");
222 }
223
224 m_private_key = std::make_shared<EC_PrivateKey_Data>(*group, private_key_bits);
225
226 if(public_key_bits.empty()) {
227 m_public_key = m_private_key->public_key(with_modular_inverse);
228 } else {
229 m_public_key = std::make_shared<EC_PublicKey_Data>(*group, public_key_bits);
230 }
231
232 m_domain_encoding = default_encoding_for(domain());
233}
234
235bool EC_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
236 if(!m_private_key) {
237 return false;
238 }
239
240 if(!EC_PublicKey::check_key(rng, strong)) {
241 return false;
242 }
243
244 // Verify that the public key is consistent with the private key.
245 // For ECKCDSA/ECGDSA the derivation is g^(x^-1), for all others it is g^x.
246 auto expected = m_private_key->public_key(m_with_modular_inverse);
247 return expected->public_key() == _public_ec_point();
248}
249
250const BigInt& EC_PublicKey::get_int_field(std::string_view field) const {
251 if(field == "public_x" || field == "public_y") {
252 throw Not_Implemented(fmt("EC_PublicKey::get_int_field no longer implements getter for {}", field));
253 } else if(field == "base_x") {
254 return this->domain().get_g_x();
255 } else if(field == "base_y") {
256 return this->domain().get_g_y();
257 } else if(field == "p") {
258 return this->domain().get_p();
259 } else if(field == "a") {
260 return this->domain().get_a();
261 } else if(field == "b") {
262 return this->domain().get_b();
263 } else if(field == "cofactor") {
264 return this->domain().get_cofactor();
265 } else if(field == "order") {
266 return this->domain().get_order();
267 } else {
268 return Public_Key::get_int_field(field);
269 }
270}
271
272const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const {
273 if(field == "x") {
274 return this->private_value();
275 } else {
276 return EC_PublicKey::get_int_field(field);
277 }
278}
279
280} // namespace Botan
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
bool parameters_are_empty() const
Definition asn1_obj.h:715
const std::vector< uint8_t > & parameters() const
Definition asn1_obj.h:693
const OID & oid() const
Definition asn1_obj.h:688
virtual const BigInt & get_int_field(std::string_view field) const
Definition pk_keys.cpp:18
virtual OID object_identifier() const
Definition pk_keys.cpp:22
static Limits DER()
Definition ber_dec.h:42
BER_Decoder start_sequence()
Definition ber_dec.h:275
BER_Decoder & decode_and_check(const T &expected, std::string_view error_msg)
Definition ber_dec.h:701
bool is_zero() const
Definition bigint.h:510
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:161
DER_Encoder & encode_octet_aligned_bitstring(std::span< const uint8_t > bytes, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition der_enc.h:210
DER_Encoder & start_explicit_context_specific(uint32_t tag)
Definition der_enc.h:122
DER_Encoder & start_sequence()
Definition der_enc.h:86
DER_Encoder & end_cons()
Definition der_enc.cpp:208
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
bool is_identity() const
Return true if this point is the identity element.
std::vector< uint8_t > serialize(EC_Point_Format format) const
Return an encoding depending on the requested format.
const BigInt & get_b() const
Definition ec_group.cpp:678
const BigInt & get_a() const
Definition ec_group.cpp:674
const BigInt & get_g_y() const
Definition ec_group.cpp:726
const BigInt & get_cofactor() const
Definition ec_group.cpp:730
const BigInt & get_p() const
Definition ec_group.cpp:670
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
Definition ec_group.cpp:814
const BigInt & get_order() const
Definition ec_group.cpp:718
size_t get_p_bits() const
Definition ec_group.cpp:654
const BigInt & get_g_x() const
Definition ec_group.cpp:722
const OID & get_curve_oid() const
Definition ec_group.cpp:738
std::vector< uint8_t > DER_encode(EC_Group_Encoding form) const
Definition ec_group.cpp:764
const EC_Scalar & _private_key() const
Definition ecc_key.cpp:135
bool m_with_modular_inverse
Definition ecc_key.h:230
const BigInt & private_value() const
Definition ecc_key.cpp:130
secure_vector< uint8_t > raw_private_key_bits() const final
Definition ecc_key.cpp:169
std::shared_ptr< const EC_PrivateKey_Data > m_private_key
Definition ecc_key.h:229
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ecc_key.cpp:235
const BigInt & get_int_field(std::string_view field) const final
Definition ecc_key.cpp:272
secure_vector< uint8_t > private_key_bits() const final
Definition ecc_key.cpp:174
const EC_Group & domain() const
Definition ecc_key.cpp:76
std::vector< uint8_t > DER_domain() const
Definition ecc_key.cpp:110
static const AlgorithmIdentifier & assert_algorithm_identifier(const AlgorithmIdentifier &alg_id, std::string_view alg_name)
Definition ecc_key.cpp:48
void set_parameter_encoding(EC_Group_Encoding enc)
Definition ecc_key.cpp:122
EC_Point_Format m_point_encoding
Definition ecc_key.h:144
EC_Group_Encoding m_domain_encoding
Definition ecc_key.h:143
size_t estimated_strength() const override
Definition ecc_key.cpp:32
AlgorithmIdentifier algorithm_identifier() const override
Definition ecc_key.cpp:98
size_t key_length() const override
Definition ecc_key.cpp:28
EC_Group_Encoding domain_format() const
Definition ecc_key.h:96
std::shared_ptr< const EC_PublicKey_Data > m_public_key
Definition ecc_key.h:142
std::vector< uint8_t > raw_public_key_bits() const override
Definition ecc_key.cpp:102
void set_point_encoding(EC_Point_Format enc)
Definition ecc_key.cpp:114
const BigInt & get_int_field(std::string_view field) const override
Definition ecc_key.cpp:250
EC_PublicKey()=default
EC_Point_Format point_encoding() const
Definition ecc_key.h:102
const EC_AffinePoint & _public_ec_point() const
Definition ecc_key.cpp:88
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ecc_key.cpp:93
std::vector< uint8_t > public_key_bits() const override
Definition ecc_key.cpp:106
static EC_Scalar from_bigint(const EC_Group &group, const BigInt &bn)
Definition ec_scalar.cpp:72
static EC_Scalar random(const EC_Group &group, RandomNumberGenerator &rng)
Definition ec_scalar.cpp:64
bool empty() const
Definition asn1_obj.h:468
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
size_t ecp_work_factor(size_t bits)
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:47
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128