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
17static 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
30static const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method;
31
32const EC_KEY_METHOD *EC_KEY_OpenSSL(void)
33{
34    return &openssl_ec_key_method;
35}
36
37const EC_KEY_METHOD *EC_KEY_get_default_method(void)
38{
39    return default_ec_key_meth;
40}
41
42void 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
50const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key)
51{
52    return key->meth;
53}
54
55int 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
73EC_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
127int 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
155EC_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
167void EC_KEY_METHOD_free(EC_KEY_METHOD *meth)
168{
169    if (meth->flags & EC_KEY_METHOD_DYNAMIC)
170        OPENSSL_free(meth);
171}
172
173void 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
191void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth,
192                              int (*keygen)(EC_KEY *key))
193{
194    meth->keygen = keygen;
195}
196
197void 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
206void 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
225void 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
239void 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
264void 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
271void 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
281void 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
303void 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}
318