/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/workfactor.h> |
18 | | |
19 | | namespace Botan { |
20 | | |
21 | 0 | size_t EC_PublicKey::key_length() const { |
22 | 0 | return domain().get_p_bits(); |
23 | 0 | } |
24 | | |
25 | 0 | size_t EC_PublicKey::estimated_strength() const { |
26 | 0 | return ecp_work_factor(key_length()); |
27 | 0 | } |
28 | | |
29 | | namespace { |
30 | | |
31 | 5.16k | EC_Group_Encoding default_encoding_for(EC_Group& group) { |
32 | 5.16k | if(group.get_curve_oid().empty()) { |
33 | 0 | return EC_Group_Encoding::Explicit; |
34 | 5.16k | } else { |
35 | 5.16k | return EC_Group_Encoding::NamedCurve; |
36 | 5.16k | } |
37 | 5.16k | } |
38 | | |
39 | | } // namespace |
40 | | |
41 | | EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, const EC_Point& pub_point) : |
42 | 3.12k | m_domain_params(dom_par), m_public_key(pub_point), m_domain_encoding(default_encoding_for(m_domain_params)) {} |
43 | | |
44 | | EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) : |
45 | | m_domain_params{EC_Group(alg_id.parameters())}, |
46 | | m_public_key{domain().OS2ECP(key_bits)}, |
47 | 0 | m_domain_encoding(default_encoding_for(m_domain_params)) {} |
48 | | |
49 | 1.13k | bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const { |
50 | 1.13k | return m_domain_params.verify_group(rng) && m_domain_params.verify_public_element(public_point()); |
51 | 1.13k | } |
52 | | |
53 | 0 | AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const { |
54 | 0 | return AlgorithmIdentifier(object_identifier(), DER_domain()); |
55 | 0 | } |
56 | | |
57 | 0 | std::vector<uint8_t> EC_PublicKey::public_key_bits() const { |
58 | 0 | return public_point().encode(point_encoding()); |
59 | 0 | } |
60 | | |
61 | 0 | void EC_PublicKey::set_point_encoding(EC_Point_Format enc) { |
62 | 0 | if(enc != EC_Point_Format::Compressed && enc != EC_Point_Format::Uncompressed && enc != EC_Point_Format::Hybrid) { |
63 | 0 | throw Invalid_Argument("Invalid point encoding for EC_PublicKey"); |
64 | 0 | } |
65 | | |
66 | 0 | m_point_encoding = enc; |
67 | 0 | } |
68 | | |
69 | 0 | void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) { |
70 | 0 | if(form == EC_Group_Encoding::NamedCurve && m_domain_params.get_curve_oid().empty()) { |
71 | 0 | throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID"); |
72 | 0 | } |
73 | | |
74 | 0 | m_domain_encoding = form; |
75 | 0 | } |
76 | | |
77 | 684 | const BigInt& EC_PrivateKey::private_value() const { |
78 | 684 | if(m_private_key == 0) { |
79 | 0 | throw Invalid_State("EC_PrivateKey::private_value - uninitialized"); |
80 | 0 | } |
81 | | |
82 | 684 | return m_private_key; |
83 | 684 | } |
84 | | |
85 | | /** |
86 | | * EC_PrivateKey constructor |
87 | | */ |
88 | | EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, |
89 | | const EC_Group& ec_group, |
90 | | const BigInt& x, |
91 | 2.04k | bool with_modular_inverse) { |
92 | 2.04k | m_domain_params = ec_group; |
93 | 2.04k | m_domain_encoding = default_encoding_for(m_domain_params); |
94 | | |
95 | 2.04k | if(x == 0) { |
96 | 821 | m_private_key = ec_group.random_scalar(rng); |
97 | 1.22k | } else { |
98 | 1.22k | m_private_key = x; |
99 | 1.22k | } |
100 | | |
101 | 2.04k | std::vector<BigInt> ws; |
102 | | |
103 | 2.04k | if(with_modular_inverse) { |
104 | | // ECKCDSA |
105 | 213 | m_public_key = domain().blinded_base_point_multiply(m_domain_params.inverse_mod_order(m_private_key), rng, ws); |
106 | 1.83k | } else { |
107 | 1.83k | m_public_key = domain().blinded_base_point_multiply(m_private_key, rng, ws); |
108 | 1.83k | } |
109 | | |
110 | 2.04k | BOTAN_ASSERT(m_public_key.on_the_curve(), "Generated public key point was on the curve"); |
111 | 2.04k | } |
112 | | |
113 | 0 | secure_vector<uint8_t> EC_PrivateKey::raw_private_key_bits() const { |
114 | 0 | return BigInt::encode_locked(m_private_key); |
115 | 0 | } |
116 | | |
117 | 0 | secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const { |
118 | 0 | return DER_Encoder() |
119 | 0 | .start_sequence() |
120 | 0 | .encode(static_cast<size_t>(1)) |
121 | 0 | .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()), ASN1_Type::OctetString) |
122 | 0 | .start_explicit_context_specific(1) |
123 | 0 | .encode(m_public_key.encode(EC_Point_Format::Uncompressed), ASN1_Type::BitString) |
124 | 0 | .end_cons() |
125 | 0 | .end_cons() |
126 | 0 | .get_contents(); |
127 | 0 | } |
128 | | |
129 | | EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, |
130 | | std::span<const uint8_t> key_bits, |
131 | 0 | bool with_modular_inverse) { |
132 | 0 | m_domain_params = EC_Group(alg_id.parameters()); |
133 | 0 | m_domain_encoding = default_encoding_for(m_domain_params); |
134 | |
|
135 | 0 | OID key_parameters; |
136 | 0 | secure_vector<uint8_t> public_key_bits; |
137 | |
|
138 | 0 | BER_Decoder(key_bits) |
139 | 0 | .start_sequence() |
140 | 0 | .decode_and_check<size_t>(1, "Unknown version code for ECC key") |
141 | 0 | .decode_octet_string_bigint(m_private_key) |
142 | 0 | .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific) |
143 | 0 | .decode_optional_string(public_key_bits, ASN1_Type::BitString, 1, ASN1_Class::ExplicitContextSpecific) |
144 | 0 | .end_cons(); |
145 | |
|
146 | 0 | if(public_key_bits.empty()) { |
147 | 0 | if(with_modular_inverse) { |
148 | | // ECKCDSA |
149 | 0 | m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key); |
150 | 0 | } else { |
151 | 0 | m_public_key = domain().get_base_point() * m_private_key; |
152 | 0 | } |
153 | |
|
154 | 0 | BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve"); |
155 | 0 | } else { |
156 | 0 | m_public_key = domain().OS2ECP(public_key_bits); |
157 | | // OS2ECP verifies that the point is on the curve |
158 | 0 | } |
159 | 0 | } |
160 | | |
161 | 0 | bool EC_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { |
162 | 0 | if(m_private_key < 1 || m_private_key >= m_domain_params.get_order()) { |
163 | 0 | return false; |
164 | 0 | } |
165 | | |
166 | 0 | return EC_PublicKey::check_key(rng, strong); |
167 | 0 | } |
168 | | |
169 | 0 | const BigInt& EC_PublicKey::get_int_field(std::string_view field) const { |
170 | 0 | if(field == "public_x") { |
171 | 0 | BOTAN_ASSERT_NOMSG(this->public_point().is_affine()); |
172 | 0 | return this->public_point().get_x(); |
173 | 0 | } else if(field == "public_y") { |
174 | 0 | BOTAN_ASSERT_NOMSG(this->public_point().is_affine()); |
175 | 0 | return this->public_point().get_y(); |
176 | 0 | } else if(field == "base_x") { |
177 | 0 | return this->domain().get_g_x(); |
178 | 0 | } else if(field == "base_y") { |
179 | 0 | return this->domain().get_g_y(); |
180 | 0 | } else if(field == "p") { |
181 | 0 | return this->domain().get_p(); |
182 | 0 | } else if(field == "a") { |
183 | 0 | return this->domain().get_a(); |
184 | 0 | } else if(field == "b") { |
185 | 0 | return this->domain().get_b(); |
186 | 0 | } else if(field == "cofactor") { |
187 | 0 | return this->domain().get_cofactor(); |
188 | 0 | } else if(field == "order") { |
189 | 0 | return this->domain().get_order(); |
190 | 0 | } else { |
191 | 0 | return Public_Key::get_int_field(field); |
192 | 0 | } |
193 | 0 | } |
194 | | |
195 | 0 | const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const { |
196 | 0 | if(field == "x") { |
197 | 0 | return this->private_value(); |
198 | 0 | } else { |
199 | 0 | return EC_PublicKey::get_int_field(field); |
200 | 0 | } |
201 | 0 | } |
202 | | |
203 | | } // namespace Botan |