1 | /* |
2 | * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include <string.h> |
11 | #include <openssl/ec.h> |
12 | #include <openssl/engine.h> |
13 | #include <openssl/err.h> |
14 | #include "ec_local.h" |
15 | |
16 | |
17 | static const EC_KEY_METHOD openssl_ec_key_method = { |
18 | "OpenSSL EC_KEY method" , |
19 | 0, |
20 | 0,0,0,0,0,0, |
21 | ossl_ec_key_gen, |
22 | ossl_ecdh_compute_key, |
23 | ossl_ecdsa_sign, |
24 | ossl_ecdsa_sign_setup, |
25 | ossl_ecdsa_sign_sig, |
26 | ossl_ecdsa_verify, |
27 | ossl_ecdsa_verify_sig |
28 | }; |
29 | |
30 | static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method; |
31 | |
32 | const EC_KEY_METHOD *EC_KEY_OpenSSL(void) |
33 | { |
34 | return &openssl_ec_key_method; |
35 | } |
36 | |
37 | const EC_KEY_METHOD *EC_KEY_get_default_method(void) |
38 | { |
39 | return default_ec_key_meth; |
40 | } |
41 | |
42 | void EC_KEY_set_default_method(const EC_KEY_METHOD *meth) |
43 | { |
44 | if (meth == NULL) |
45 | default_ec_key_meth = &openssl_ec_key_method; |
46 | else |
47 | default_ec_key_meth = meth; |
48 | } |
49 | |
50 | const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key) |
51 | { |
52 | return key->meth; |
53 | } |
54 | |
55 | int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) |
56 | { |
57 | void (*finish)(EC_KEY *key) = key->meth->finish; |
58 | |
59 | if (finish != NULL) |
60 | finish(key); |
61 | |
62 | #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) |
63 | ENGINE_finish(key->engine); |
64 | key->engine = NULL; |
65 | #endif |
66 | |
67 | key->meth = meth; |
68 | if (meth->init != NULL) |
69 | return meth->init(key); |
70 | return 1; |
71 | } |
72 | |
73 | EC_KEY *ec_key_new_method_int(OPENSSL_CTX *libctx, ENGINE *engine) |
74 | { |
75 | EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); |
76 | |
77 | if (ret == NULL) { |
78 | ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_MALLOC_FAILURE); |
79 | return NULL; |
80 | } |
81 | |
82 | ret->libctx = libctx; |
83 | |
84 | ret->references = 1; |
85 | ret->lock = CRYPTO_THREAD_lock_new(); |
86 | if (ret->lock == NULL) { |
87 | ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_MALLOC_FAILURE); |
88 | OPENSSL_free(ret); |
89 | return NULL; |
90 | } |
91 | |
92 | ret->meth = EC_KEY_get_default_method(); |
93 | #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) |
94 | if (engine != NULL) { |
95 | if (!ENGINE_init(engine)) { |
96 | ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_ENGINE_LIB); |
97 | goto err; |
98 | } |
99 | ret->engine = engine; |
100 | } else |
101 | ret->engine = ENGINE_get_default_EC(); |
102 | if (ret->engine != NULL) { |
103 | ret->meth = ENGINE_get_EC(ret->engine); |
104 | if (ret->meth == NULL) { |
105 | ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_ENGINE_LIB); |
106 | goto err; |
107 | } |
108 | } |
109 | #endif |
110 | |
111 | ret->version = 1; |
112 | ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; |
113 | |
114 | /* No ex_data inside the FIPS provider */ |
115 | #ifndef FIPS_MODE |
116 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { |
117 | goto err; |
118 | } |
119 | #endif |
120 | |
121 | if (ret->meth->init != NULL && ret->meth->init(ret) == 0) { |
122 | ECerr(EC_F_EC_KEY_NEW_METHOD_INT, ERR_R_INIT_FAIL); |
123 | goto err; |
124 | } |
125 | return ret; |
126 | |
127 | err: |
128 | EC_KEY_free(ret); |
129 | return NULL; |
130 | } |
131 | |
132 | #ifndef FIPS_MODE |
133 | EC_KEY *EC_KEY_new_method(ENGINE *engine) |
134 | { |
135 | return ec_key_new_method_int(NULL, engine); |
136 | } |
137 | #endif |
138 | |
139 | int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, |
140 | const EC_KEY *eckey, |
141 | void *(*KDF) (const void *in, size_t inlen, void *out, |
142 | size_t *outlen)) |
143 | { |
144 | unsigned char *sec = NULL; |
145 | size_t seclen; |
146 | if (eckey->meth->compute_key == NULL) { |
147 | ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED); |
148 | return 0; |
149 | } |
150 | if (outlen > INT_MAX) { |
151 | ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH); |
152 | return 0; |
153 | } |
154 | if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey)) |
155 | return 0; |
156 | if (KDF != NULL) { |
157 | KDF(sec, seclen, out, &outlen); |
158 | } else { |
159 | if (outlen > seclen) |
160 | outlen = seclen; |
161 | memcpy(out, sec, outlen); |
162 | } |
163 | OPENSSL_clear_free(sec, seclen); |
164 | return outlen; |
165 | } |
166 | |
167 | EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth) |
168 | { |
169 | EC_KEY_METHOD *ret = OPENSSL_zalloc(sizeof(*meth)); |
170 | |
171 | if (ret == NULL) |
172 | return NULL; |
173 | if (meth != NULL) |
174 | *ret = *meth; |
175 | ret->flags |= EC_KEY_METHOD_DYNAMIC; |
176 | return ret; |
177 | } |
178 | |
179 | void EC_KEY_METHOD_free(EC_KEY_METHOD *meth) |
180 | { |
181 | if (meth->flags & EC_KEY_METHOD_DYNAMIC) |
182 | OPENSSL_free(meth); |
183 | } |
184 | |
185 | void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, |
186 | int (*init)(EC_KEY *key), |
187 | void (*finish)(EC_KEY *key), |
188 | int (*copy)(EC_KEY *dest, const EC_KEY *src), |
189 | int (*set_group)(EC_KEY *key, const EC_GROUP *grp), |
190 | int (*set_private)(EC_KEY *key, |
191 | const BIGNUM *priv_key), |
192 | int (*set_public)(EC_KEY *key, |
193 | const EC_POINT *pub_key)) |
194 | { |
195 | meth->init = init; |
196 | meth->finish = finish; |
197 | meth->copy = copy; |
198 | meth->set_group = set_group; |
199 | meth->set_private = set_private; |
200 | meth->set_public = set_public; |
201 | } |
202 | |
203 | void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, |
204 | int (*keygen)(EC_KEY *key)) |
205 | { |
206 | meth->keygen = keygen; |
207 | } |
208 | |
209 | void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, |
210 | int (*ckey)(unsigned char **psec, |
211 | size_t *pseclen, |
212 | const EC_POINT *pub_key, |
213 | const EC_KEY *ecdh)) |
214 | { |
215 | meth->compute_key = ckey; |
216 | } |
217 | |
218 | void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, |
219 | int (*sign)(int type, const unsigned char *dgst, |
220 | int dlen, unsigned char *sig, |
221 | unsigned int *siglen, |
222 | const BIGNUM *kinv, const BIGNUM *r, |
223 | EC_KEY *eckey), |
224 | int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, |
225 | BIGNUM **kinvp, BIGNUM **rp), |
226 | ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, |
227 | int dgst_len, |
228 | const BIGNUM *in_kinv, |
229 | const BIGNUM *in_r, |
230 | EC_KEY *eckey)) |
231 | { |
232 | meth->sign = sign; |
233 | meth->sign_setup = sign_setup; |
234 | meth->sign_sig = sign_sig; |
235 | } |
236 | |
237 | void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, |
238 | int (*verify)(int type, const unsigned |
239 | char *dgst, int dgst_len, |
240 | const unsigned char *sigbuf, |
241 | int sig_len, EC_KEY *eckey), |
242 | int (*verify_sig)(const unsigned char *dgst, |
243 | int dgst_len, |
244 | const ECDSA_SIG *sig, |
245 | EC_KEY *eckey)) |
246 | { |
247 | meth->verify = verify; |
248 | meth->verify_sig = verify_sig; |
249 | } |
250 | |
251 | void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, |
252 | int (**pinit)(EC_KEY *key), |
253 | void (**pfinish)(EC_KEY *key), |
254 | int (**pcopy)(EC_KEY *dest, const EC_KEY *src), |
255 | int (**pset_group)(EC_KEY *key, |
256 | const EC_GROUP *grp), |
257 | int (**pset_private)(EC_KEY *key, |
258 | const BIGNUM *priv_key), |
259 | int (**pset_public)(EC_KEY *key, |
260 | const EC_POINT *pub_key)) |
261 | { |
262 | if (pinit != NULL) |
263 | *pinit = meth->init; |
264 | if (pfinish != NULL) |
265 | *pfinish = meth->finish; |
266 | if (pcopy != NULL) |
267 | *pcopy = meth->copy; |
268 | if (pset_group != NULL) |
269 | *pset_group = meth->set_group; |
270 | if (pset_private != NULL) |
271 | *pset_private = meth->set_private; |
272 | if (pset_public != NULL) |
273 | *pset_public = meth->set_public; |
274 | } |
275 | |
276 | void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, |
277 | int (**pkeygen)(EC_KEY *key)) |
278 | { |
279 | if (pkeygen != NULL) |
280 | *pkeygen = meth->keygen; |
281 | } |
282 | |
283 | void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, |
284 | int (**pck)(unsigned char **pout, |
285 | size_t *poutlen, |
286 | const EC_POINT *pub_key, |
287 | const EC_KEY *ecdh)) |
288 | { |
289 | if (pck != NULL) |
290 | *pck = meth->compute_key; |
291 | } |
292 | |
293 | void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, |
294 | int (**psign)(int type, const unsigned char *dgst, |
295 | int dlen, unsigned char *sig, |
296 | unsigned int *siglen, |
297 | const BIGNUM *kinv, const BIGNUM *r, |
298 | EC_KEY *eckey), |
299 | int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, |
300 | BIGNUM **kinvp, BIGNUM **rp), |
301 | ECDSA_SIG *(**psign_sig)(const unsigned char *dgst, |
302 | int dgst_len, |
303 | const BIGNUM *in_kinv, |
304 | const BIGNUM *in_r, |
305 | EC_KEY *eckey)) |
306 | { |
307 | if (psign != NULL) |
308 | *psign = meth->sign; |
309 | if (psign_setup != NULL) |
310 | *psign_setup = meth->sign_setup; |
311 | if (psign_sig != NULL) |
312 | *psign_sig = meth->sign_sig; |
313 | } |
314 | |
315 | void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, |
316 | int (**pverify)(int type, const unsigned |
317 | char *dgst, int dgst_len, |
318 | const unsigned char *sigbuf, |
319 | int sig_len, EC_KEY *eckey), |
320 | int (**pverify_sig)(const unsigned char *dgst, |
321 | int dgst_len, |
322 | const ECDSA_SIG *sig, |
323 | EC_KEY *eckey)) |
324 | { |
325 | if (pverify != NULL) |
326 | *pverify = meth->verify; |
327 | if (pverify_sig != NULL) |
328 | *pverify_sig = meth->verify_sig; |
329 | } |
330 | |