1 | /*
|
---|
2 | * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the OpenSSL license (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 | #ifndef OPENSSL_NO_ENGINE
|
---|
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(ENGINE *engine)
|
---|
74 | {
|
---|
75 | EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
|
---|
76 |
|
---|
77 | if (ret == NULL) {
|
---|
78 | ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
|
---|
79 | return NULL;
|
---|
80 | }
|
---|
81 |
|
---|
82 | ret->references = 1;
|
---|
83 | ret->lock = CRYPTO_THREAD_lock_new();
|
---|
84 | if (ret->lock == NULL) {
|
---|
85 | ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_MALLOC_FAILURE);
|
---|
86 | OPENSSL_free(ret);
|
---|
87 | return NULL;
|
---|
88 | }
|
---|
89 |
|
---|
90 | ret->meth = EC_KEY_get_default_method();
|
---|
91 | #ifndef OPENSSL_NO_ENGINE
|
---|
92 | if (engine != NULL) {
|
---|
93 | if (!ENGINE_init(engine)) {
|
---|
94 | ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
|
---|
95 | goto err;
|
---|
96 | }
|
---|
97 | ret->engine = engine;
|
---|
98 | } else
|
---|
99 | ret->engine = ENGINE_get_default_EC();
|
---|
100 | if (ret->engine != NULL) {
|
---|
101 | ret->meth = ENGINE_get_EC(ret->engine);
|
---|
102 | if (ret->meth == NULL) {
|
---|
103 | ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_ENGINE_LIB);
|
---|
104 | goto err;
|
---|
105 | }
|
---|
106 | }
|
---|
107 | #endif
|
---|
108 |
|
---|
109 | ret->version = 1;
|
---|
110 | ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
|
---|
111 |
|
---|
112 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) {
|
---|
113 | goto err;
|
---|
114 | }
|
---|
115 |
|
---|
116 | if (ret->meth->init != NULL && ret->meth->init(ret) == 0) {
|
---|
117 | ECerr(EC_F_EC_KEY_NEW_METHOD, ERR_R_INIT_FAIL);
|
---|
118 | goto err;
|
---|
119 | }
|
---|
120 | return ret;
|
---|
121 |
|
---|
122 | err:
|
---|
123 | EC_KEY_free(ret);
|
---|
124 | return NULL;
|
---|
125 | }
|
---|
126 |
|
---|
127 | int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
|
---|
128 | const EC_KEY *eckey,
|
---|
129 | void *(*KDF) (const void *in, size_t inlen, void *out,
|
---|
130 | size_t *outlen))
|
---|
131 | {
|
---|
132 | unsigned char *sec = NULL;
|
---|
133 | size_t seclen;
|
---|
134 | if (eckey->meth->compute_key == NULL) {
|
---|
135 | ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_OPERATION_NOT_SUPPORTED);
|
---|
136 | return 0;
|
---|
137 | }
|
---|
138 | if (outlen > INT_MAX) {
|
---|
139 | ECerr(EC_F_ECDH_COMPUTE_KEY, EC_R_INVALID_OUTPUT_LENGTH);
|
---|
140 | return 0;
|
---|
141 | }
|
---|
142 | if (!eckey->meth->compute_key(&sec, &seclen, pub_key, eckey))
|
---|
143 | return 0;
|
---|
144 | if (KDF != NULL) {
|
---|
145 | KDF(sec, seclen, out, &outlen);
|
---|
146 | } else {
|
---|
147 | if (outlen > seclen)
|
---|
148 | outlen = seclen;
|
---|
149 | memcpy(out, sec, outlen);
|
---|
150 | }
|
---|
151 | OPENSSL_clear_free(sec, seclen);
|
---|
152 | return outlen;
|
---|
153 | }
|
---|
154 |
|
---|
155 | EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth)
|
---|
156 | {
|
---|
157 | EC_KEY_METHOD *ret = OPENSSL_zalloc(sizeof(*meth));
|
---|
158 |
|
---|
159 | if (ret == NULL)
|
---|
160 | return NULL;
|
---|
161 | if (meth != NULL)
|
---|
162 | *ret = *meth;
|
---|
163 | ret->flags |= EC_KEY_METHOD_DYNAMIC;
|
---|
164 | return ret;
|
---|
165 | }
|
---|
166 |
|
---|
167 | void EC_KEY_METHOD_free(EC_KEY_METHOD *meth)
|
---|
168 | {
|
---|
169 | if (meth->flags & EC_KEY_METHOD_DYNAMIC)
|
---|
170 | OPENSSL_free(meth);
|
---|
171 | }
|
---|
172 |
|
---|
173 | void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
|
---|
174 | int (*init)(EC_KEY *key),
|
---|
175 | void (*finish)(EC_KEY *key),
|
---|
176 | int (*copy)(EC_KEY *dest, const EC_KEY *src),
|
---|
177 | int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
|
---|
178 | int (*set_private)(EC_KEY *key,
|
---|
179 | const BIGNUM *priv_key),
|
---|
180 | int (*set_public)(EC_KEY *key,
|
---|
181 | const EC_POINT *pub_key))
|
---|
182 | {
|
---|
183 | meth->init = init;
|
---|
184 | meth->finish = finish;
|
---|
185 | meth->copy = copy;
|
---|
186 | meth->set_group = set_group;
|
---|
187 | meth->set_private = set_private;
|
---|
188 | meth->set_public = set_public;
|
---|
189 | }
|
---|
190 |
|
---|
191 | void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
|
---|
192 | int (*keygen)(EC_KEY *key))
|
---|
193 | {
|
---|
194 | meth->keygen = keygen;
|
---|
195 | }
|
---|
196 |
|
---|
197 | void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
|
---|
198 | int (*ckey)(unsigned char **psec,
|
---|
199 | size_t *pseclen,
|
---|
200 | const EC_POINT *pub_key,
|
---|
201 | const EC_KEY *ecdh))
|
---|
202 | {
|
---|
203 | meth->compute_key = ckey;
|
---|
204 | }
|
---|
205 |
|
---|
206 | void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
|
---|
207 | int (*sign)(int type, const unsigned char *dgst,
|
---|
208 | int dlen, unsigned char *sig,
|
---|
209 | unsigned int *siglen,
|
---|
210 | const BIGNUM *kinv, const BIGNUM *r,
|
---|
211 | EC_KEY *eckey),
|
---|
212 | int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
|
---|
213 | BIGNUM **kinvp, BIGNUM **rp),
|
---|
214 | ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
|
---|
215 | int dgst_len,
|
---|
216 | const BIGNUM *in_kinv,
|
---|
217 | const BIGNUM *in_r,
|
---|
218 | EC_KEY *eckey))
|
---|
219 | {
|
---|
220 | meth->sign = sign;
|
---|
221 | meth->sign_setup = sign_setup;
|
---|
222 | meth->sign_sig = sign_sig;
|
---|
223 | }
|
---|
224 |
|
---|
225 | void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth,
|
---|
226 | int (*verify)(int type, const unsigned
|
---|
227 | char *dgst, int dgst_len,
|
---|
228 | const unsigned char *sigbuf,
|
---|
229 | int sig_len, EC_KEY *eckey),
|
---|
230 | int (*verify_sig)(const unsigned char *dgst,
|
---|
231 | int dgst_len,
|
---|
232 | const ECDSA_SIG *sig,
|
---|
233 | EC_KEY *eckey))
|
---|
234 | {
|
---|
235 | meth->verify = verify;
|
---|
236 | meth->verify_sig = verify_sig;
|
---|
237 | }
|
---|
238 |
|
---|
239 | void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth,
|
---|
240 | int (**pinit)(EC_KEY *key),
|
---|
241 | void (**pfinish)(EC_KEY *key),
|
---|
242 | int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
|
---|
243 | int (**pset_group)(EC_KEY *key,
|
---|
244 | const EC_GROUP *grp),
|
---|
245 | int (**pset_private)(EC_KEY *key,
|
---|
246 | const BIGNUM *priv_key),
|
---|
247 | int (**pset_public)(EC_KEY *key,
|
---|
248 | const EC_POINT *pub_key))
|
---|
249 | {
|
---|
250 | if (pinit != NULL)
|
---|
251 | *pinit = meth->init;
|
---|
252 | if (pfinish != NULL)
|
---|
253 | *pfinish = meth->finish;
|
---|
254 | if (pcopy != NULL)
|
---|
255 | *pcopy = meth->copy;
|
---|
256 | if (pset_group != NULL)
|
---|
257 | *pset_group = meth->set_group;
|
---|
258 | if (pset_private != NULL)
|
---|
259 | *pset_private = meth->set_private;
|
---|
260 | if (pset_public != NULL)
|
---|
261 | *pset_public = meth->set_public;
|
---|
262 | }
|
---|
263 |
|
---|
264 | void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth,
|
---|
265 | int (**pkeygen)(EC_KEY *key))
|
---|
266 | {
|
---|
267 | if (pkeygen != NULL)
|
---|
268 | *pkeygen = meth->keygen;
|
---|
269 | }
|
---|
270 |
|
---|
271 | void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
|
---|
272 | int (**pck)(unsigned char **pout,
|
---|
273 | size_t *poutlen,
|
---|
274 | const EC_POINT *pub_key,
|
---|
275 | const EC_KEY *ecdh))
|
---|
276 | {
|
---|
277 | if (pck != NULL)
|
---|
278 | *pck = meth->compute_key;
|
---|
279 | }
|
---|
280 |
|
---|
281 | void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth,
|
---|
282 | int (**psign)(int type, const unsigned char *dgst,
|
---|
283 | int dlen, unsigned char *sig,
|
---|
284 | unsigned int *siglen,
|
---|
285 | const BIGNUM *kinv, const BIGNUM *r,
|
---|
286 | EC_KEY *eckey),
|
---|
287 | int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
|
---|
288 | BIGNUM **kinvp, BIGNUM **rp),
|
---|
289 | ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
|
---|
290 | int dgst_len,
|
---|
291 | const BIGNUM *in_kinv,
|
---|
292 | const BIGNUM *in_r,
|
---|
293 | EC_KEY *eckey))
|
---|
294 | {
|
---|
295 | if (psign != NULL)
|
---|
296 | *psign = meth->sign;
|
---|
297 | if (psign_setup != NULL)
|
---|
298 | *psign_setup = meth->sign_setup;
|
---|
299 | if (psign_sig != NULL)
|
---|
300 | *psign_sig = meth->sign_sig;
|
---|
301 | }
|
---|
302 |
|
---|
303 | void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth,
|
---|
304 | int (**pverify)(int type, const unsigned
|
---|
305 | char *dgst, int dgst_len,
|
---|
306 | const unsigned char *sigbuf,
|
---|
307 | int sig_len, EC_KEY *eckey),
|
---|
308 | int (**pverify_sig)(const unsigned char *dgst,
|
---|
309 | int dgst_len,
|
---|
310 | const ECDSA_SIG *sig,
|
---|
311 | EC_KEY *eckey))
|
---|
312 | {
|
---|
313 | if (pverify != NULL)
|
---|
314 | *pverify = meth->verify;
|
---|
315 | if (pverify_sig != NULL)
|
---|
316 | *pverify_sig = meth->verify_sig;
|
---|
317 | }
|
---|