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