/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 | | #include <botan/numthry.h> |
12 | | #include <botan/der_enc.h> |
13 | | #include <botan/ber_dec.h> |
14 | | #include <botan/secmem.h> |
15 | | #include <botan/point_gfp.h> |
16 | | #include <botan/workfactor.h> |
17 | | |
18 | | namespace Botan { |
19 | | |
20 | | size_t EC_PublicKey::key_length() const |
21 | 654 | { |
22 | 654 | return domain().get_p_bits(); |
23 | 654 | } |
24 | | |
25 | | size_t EC_PublicKey::estimated_strength() const |
26 | 0 | { |
27 | 0 | return ecp_work_factor(key_length()); |
28 | 0 | } |
29 | | |
30 | | EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, |
31 | | const PointGFp& pub_point) : |
32 | | m_domain_params(dom_par), m_public_key(pub_point) |
33 | 432 | { |
34 | 432 | if (!dom_par.get_curve_oid().empty()) |
35 | 432 | m_domain_encoding = EC_DOMPAR_ENC_OID; |
36 | 0 | else |
37 | 0 | m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; |
38 | 432 | |
39 | | #if 0 |
40 | | if(domain().get_curve() != public_point().get_curve()) |
41 | | throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor"); |
42 | | #endif |
43 | 432 | } |
44 | | |
45 | | EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, |
46 | | const std::vector<uint8_t>& key_bits) : |
47 | | m_domain_params{EC_Group(alg_id.get_parameters())}, |
48 | | m_public_key{domain().OS2ECP(key_bits)} |
49 | 2.66k | { |
50 | 2.66k | if (!domain().get_curve_oid().empty()) |
51 | 1.51k | m_domain_encoding = EC_DOMPAR_ENC_OID; |
52 | 1.14k | else |
53 | 1.14k | m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; |
54 | 2.66k | } |
55 | | |
56 | | bool EC_PublicKey::check_key(RandomNumberGenerator& rng, |
57 | | bool) const |
58 | 0 | { |
59 | 0 | return m_domain_params.verify_group(rng) && |
60 | 0 | m_domain_params.verify_public_element(public_point()); |
61 | 0 | } |
62 | | |
63 | | |
64 | | AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const |
65 | 0 | { |
66 | 0 | return AlgorithmIdentifier(get_oid(), DER_domain()); |
67 | 0 | } |
68 | | |
69 | | std::vector<uint8_t> EC_PublicKey::public_key_bits() const |
70 | 0 | { |
71 | 0 | return public_point().encode(point_encoding()); |
72 | 0 | } |
73 | | |
74 | | void EC_PublicKey::set_point_encoding(PointGFp::Compression_Type enc) |
75 | 0 | { |
76 | 0 | if(enc != PointGFp::COMPRESSED && |
77 | 0 | enc != PointGFp::UNCOMPRESSED && |
78 | 0 | enc != PointGFp::HYBRID) |
79 | 0 | throw Invalid_Argument("Invalid point encoding for EC_PublicKey"); |
80 | 0 | |
81 | 0 | m_point_encoding = enc; |
82 | 0 | } |
83 | | |
84 | | void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) |
85 | 0 | { |
86 | 0 | if(form != EC_DOMPAR_ENC_EXPLICIT && |
87 | 0 | form != EC_DOMPAR_ENC_IMPLICITCA && |
88 | 0 | form != EC_DOMPAR_ENC_OID) |
89 | 0 | throw Invalid_Argument("Invalid encoding form for EC-key object specified"); |
90 | 0 | |
91 | 0 | if((form == EC_DOMPAR_ENC_OID) && (m_domain_params.get_curve_oid().empty())) |
92 | 0 | throw Invalid_Argument("Invalid encoding form OID specified for " |
93 | 0 | "EC-key object whose corresponding domain " |
94 | 0 | "parameters are without oid"); |
95 | 0 | |
96 | 0 | m_domain_encoding = form; |
97 | 0 | } |
98 | | |
99 | | const BigInt& EC_PrivateKey::private_value() const |
100 | 11.8k | { |
101 | 11.8k | if(m_private_key == 0) |
102 | 0 | throw Invalid_State("EC_PrivateKey::private_value - uninitialized"); |
103 | 11.8k | |
104 | 11.8k | return m_private_key; |
105 | 11.8k | } |
106 | | |
107 | | /** |
108 | | * EC_PrivateKey constructor |
109 | | */ |
110 | | EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, |
111 | | const EC_Group& ec_group, |
112 | | const BigInt& x, |
113 | | bool with_modular_inverse) |
114 | 18.6k | { |
115 | 18.6k | m_domain_params = ec_group; |
116 | 18.6k | if (!ec_group.get_curve_oid().empty()) |
117 | 18.6k | m_domain_encoding = EC_DOMPAR_ENC_OID; |
118 | 0 | else |
119 | 0 | m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; |
120 | 18.6k | |
121 | 18.6k | if(x == 0) |
122 | 18.6k | { |
123 | 18.6k | m_private_key = ec_group.random_scalar(rng); |
124 | 18.6k | } |
125 | 0 | else |
126 | 0 | { |
127 | 0 | m_private_key = x; |
128 | 0 | } |
129 | 18.6k | |
130 | 18.6k | std::vector<BigInt> ws; |
131 | 18.6k | |
132 | 18.6k | if(with_modular_inverse) |
133 | 0 | { |
134 | | // ECKCDSA |
135 | 0 | m_public_key = domain().blinded_base_point_multiply( |
136 | 0 | m_domain_params.inverse_mod_order(m_private_key), rng, ws); |
137 | 0 | } |
138 | 18.6k | else |
139 | 18.6k | { |
140 | 18.6k | m_public_key = domain().blinded_base_point_multiply(m_private_key, rng, ws); |
141 | 18.6k | } |
142 | 18.6k | |
143 | 18.6k | BOTAN_ASSERT(m_public_key.on_the_curve(), |
144 | 18.6k | "Generated public key point was on the curve"); |
145 | 18.6k | } |
146 | | |
147 | | secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const |
148 | 0 | { |
149 | 0 | return DER_Encoder() |
150 | 0 | .start_cons(SEQUENCE) |
151 | 0 | .encode(static_cast<size_t>(1)) |
152 | 0 | .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()), OCTET_STRING) |
153 | 0 | .start_cons(ASN1_Tag(1), PRIVATE) |
154 | 0 | .encode(m_public_key.encode(PointGFp::Compression_Type::UNCOMPRESSED), BIT_STRING) |
155 | 0 | .end_cons() |
156 | 0 | .end_cons() |
157 | 0 | .get_contents(); |
158 | 0 | } |
159 | | |
160 | | EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, |
161 | | const secure_vector<uint8_t>& key_bits, |
162 | | bool with_modular_inverse) |
163 | 1.51k | { |
164 | 1.51k | m_domain_params = EC_Group(alg_id.get_parameters()); |
165 | 1.51k | m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; |
166 | 1.51k | |
167 | 1.51k | if (!domain().get_curve_oid().empty()) |
168 | 1.04k | m_domain_encoding = EC_DOMPAR_ENC_OID; |
169 | 465 | else |
170 | 465 | m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; |
171 | 1.51k | |
172 | 1.51k | OID key_parameters; |
173 | 1.51k | secure_vector<uint8_t> public_key_bits; |
174 | 1.51k | |
175 | 1.51k | BER_Decoder(key_bits) |
176 | 1.51k | .start_cons(SEQUENCE) |
177 | 1.51k | .decode_and_check<size_t>(1, "Unknown version code for ECC key") |
178 | 1.51k | .decode_octet_string_bigint(m_private_key) |
179 | 1.51k | .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) |
180 | 1.51k | .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) |
181 | 1.51k | .end_cons(); |
182 | 1.51k | |
183 | 1.51k | if(public_key_bits.empty()) |
184 | 363 | { |
185 | 363 | if(with_modular_inverse) |
186 | 0 | { |
187 | | // ECKCDSA |
188 | 0 | m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key); |
189 | 0 | } |
190 | 363 | else |
191 | 363 | { |
192 | 363 | m_public_key = domain().get_base_point() * m_private_key; |
193 | 363 | } |
194 | 363 | |
195 | 363 | BOTAN_ASSERT(m_public_key.on_the_curve(), |
196 | 363 | "Public point derived from loaded key was on the curve"); |
197 | 363 | } |
198 | 1.14k | else |
199 | 1.14k | { |
200 | 1.14k | m_public_key = domain().OS2ECP(public_key_bits); |
201 | | // OS2ECP verifies that the point is on the curve |
202 | 1.14k | } |
203 | 1.51k | } |
204 | | |
205 | | } |