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