Run the withlibctx.pl script
[openssl.git] / providers / implementations / keymgmt / ec_kmgmt.c
1 /*
2  * Copyright 2020 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/ECDSA low level APIs are deprecated for public use, but still ok for
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15
16 #include "e_os.h" /* strcasecmp */
17 #include <string.h>
18 #include <openssl/core_dispatch.h>
19 #include <openssl/core_names.h>
20 #include <openssl/bn.h>
21 #include <openssl/err.h>
22 #include <openssl/objects.h>
23 #include "crypto/bn.h"
24 #include "crypto/ec.h"
25 #include "prov/implementations.h"
26 #include "prov/providercommon.h"
27 #include "prov/providercommonerr.h"
28 #include "prov/provider_ctx.h"
29 #include "internal/param_build_set.h"
30 #include "crypto/sm2.h"
31
32 static OSSL_FUNC_keymgmt_new_fn ec_newdata;
33 static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
34 static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;
35 static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
36 static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
37 static OSSL_FUNC_keymgmt_gen_fn ec_gen;
38 static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
39 static OSSL_FUNC_keymgmt_load_fn ec_load;
40 static OSSL_FUNC_keymgmt_free_fn ec_freedata;
41 static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
42 static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
43 static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;
44 static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;
45 static OSSL_FUNC_keymgmt_has_fn ec_has;
46 static OSSL_FUNC_keymgmt_match_fn ec_match;
47 static OSSL_FUNC_keymgmt_validate_fn ec_validate;
48 static OSSL_FUNC_keymgmt_import_fn ec_import;
49 static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
50 static OSSL_FUNC_keymgmt_export_fn ec_export;
51 static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
52 static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
53 #ifndef OPENSSL_NO_SM2
54 static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
55 static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
56 static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
57 static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
58 static OSSL_FUNC_keymgmt_import_fn sm2_import;
59 static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
60 #endif
61
62 #define EC_DEFAULT_MD "SHA256"
63 #define EC_POSSIBLE_SELECTIONS                                                 \
64     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
65 #define SM2_DEFAULT_MD "SM3"
66
67 static
68 const char *ec_query_operation_name(int operation_id)
69 {
70     switch (operation_id) {
71     case OSSL_OP_KEYEXCH:
72         return "ECDH";
73     case OSSL_OP_SIGNATURE:
74         return "ECDSA";
75     }
76     return NULL;
77 }
78
79 #ifndef OPENSSL_NO_SM2
80 static
81 const char *sm2_query_operation_name(int operation_id)
82 {
83     switch (operation_id) {
84     case OSSL_OP_SIGNATURE:
85         return "SM2";
86     }
87     return NULL;
88 }
89 #endif
90
91 /*
92  * Callers of key_to_params MUST make sure that domparams_to_params is also
93  * called!
94  *
95  * This function only exports the bare keypair, domain parameters and other
96  * parameters are exported separately.
97  */
98 static ossl_inline
99 int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
100                   OSSL_PARAM params[], int include_private,
101                   unsigned char **pub_key)
102 {
103     BIGNUM *x = NULL, *y = NULL;
104     const BIGNUM *priv_key = NULL;
105     const EC_POINT *pub_point = NULL;
106     const EC_GROUP *ecg = NULL;
107     size_t pub_key_len = 0;
108     int ret = 0;
109     BN_CTX *bnctx = NULL;
110
111     if (eckey == NULL
112         || (ecg = EC_KEY_get0_group(eckey)) == NULL)
113         return 0;
114
115     priv_key = EC_KEY_get0_private_key(eckey);
116     pub_point = EC_KEY_get0_public_key(eckey);
117
118     if (pub_point != NULL) {
119         OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;
120         /*
121          * EC_POINT_point2buf() can generate random numbers in some
122          * implementations so we need to ensure we use the correct libctx.
123          */
124         bnctx = BN_CTX_new_ex(ec_key_get_libctx(eckey));
125         if (bnctx == NULL)
126             goto err;
127
128
129         /* If we are doing a get then check first before decoding the point */
130         if (tmpl == NULL) {
131             p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
132             px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);
133             py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);
134         }
135
136         if (p != NULL || tmpl != NULL) {
137             /* convert pub_point to a octet string according to the SECG standard */
138             if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
139                                                   POINT_CONVERSION_COMPRESSED,
140                                                   pub_key, bnctx)) == 0
141                 || !ossl_param_build_set_octet_string(tmpl, p,
142                                                       OSSL_PKEY_PARAM_PUB_KEY,
143                                                       *pub_key, pub_key_len))
144                 goto err;
145         }
146         if (px != NULL || py != NULL) {
147             if (px != NULL)
148                 x = BN_CTX_get(bnctx);
149             if (py != NULL)
150                 y = BN_CTX_get(bnctx);
151
152             if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))
153                 goto err;
154             if (px != NULL
155                 && !ossl_param_build_set_bn(tmpl, px,
156                                             OSSL_PKEY_PARAM_EC_PUB_X, x))
157                 goto err;
158             if (py != NULL
159                 && !ossl_param_build_set_bn(tmpl, py,
160                                             OSSL_PKEY_PARAM_EC_PUB_Y, y))
161                 goto err;
162         }
163     }
164
165     if (priv_key != NULL && include_private) {
166         size_t sz;
167         int ecbits;
168
169         /*
170          * Key import/export should never leak the bit length of the secret
171          * scalar in the key.
172          *
173          * For this reason, on export we use padded BIGNUMs with fixed length.
174          *
175          * When importing we also should make sure that, even if short lived,
176          * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
177          * soon as possible, so that any processing of this BIGNUM might opt for
178          * constant time implementations in the backend.
179          *
180          * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
181          * to preallocate the BIGNUM internal buffer to a fixed public size big
182          * enough that operations performed during the processing never trigger
183          * a realloc which would leak the size of the scalar through memory
184          * accesses.
185          *
186          * Fixed Length
187          * ------------
188          *
189          * The order of the large prime subgroup of the curve is our choice for
190          * a fixed public size, as that is generally the upper bound for
191          * generating a private key in EC cryptosystems and should fit all valid
192          * secret scalars.
193          *
194          * For padding on export we just use the bit length of the order
195          * converted to bytes (rounding up).
196          *
197          * For preallocating the BIGNUM storage we look at the number of "words"
198          * required for the internal representation of the order, and we
199          * preallocate 2 extra "words" in case any of the subsequent processing
200          * might temporarily overflow the order length.
201          */
202         ecbits = EC_GROUP_order_bits(ecg);
203         if (ecbits <= 0)
204             goto err;
205         sz = (ecbits + 7 ) / 8;
206
207         if (!ossl_param_build_set_bn_pad(tmpl, params,
208                                          OSSL_PKEY_PARAM_PRIV_KEY,
209                                          priv_key, sz))
210             goto err;
211     }
212     ret = 1;
213  err:
214     BN_CTX_free(bnctx);
215     return ret;
216 }
217
218 static ossl_inline
219 int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
220                           OSSL_PARAM params[])
221 {
222     int ecdh_cofactor_mode = 0;
223
224     if (ec == NULL)
225         return 0;
226
227     ecdh_cofactor_mode =
228         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
229     return ossl_param_build_set_int(tmpl, params,
230                                     OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
231                                     ecdh_cofactor_mode);
232 }
233
234 static
235 void *ec_newdata(void *provctx)
236 {
237     if (!ossl_prov_is_running())
238         return NULL;
239     return EC_KEY_new_ex(PROV_LIBRARY_CONTEXT_OF(provctx), NULL);
240 }
241
242 static
243 void ec_freedata(void *keydata)
244 {
245     EC_KEY_free(keydata);
246 }
247
248 static
249 int ec_has(void *keydata, int selection)
250 {
251     EC_KEY *ec = keydata;
252     int ok = 0;
253
254     if (ossl_prov_is_running() && ec != NULL) {
255         if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
256             ok = 1;
257
258         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
259             ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
260         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
261             ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
262         if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
263             ok = ok && (EC_KEY_get0_group(ec) != NULL);
264         /*
265          * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
266          * available, so no extra check is needed other than the previous one
267          * against EC_POSSIBLE_SELECTIONS.
268          */
269     }
270     return ok;
271 }
272
273 static int ec_match(const void *keydata1, const void *keydata2, int selection)
274 {
275     const EC_KEY *ec1 = keydata1;
276     const EC_KEY *ec2 = keydata2;
277     const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
278     const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
279     BN_CTX *ctx = NULL;
280     int ok = 1;
281
282     if (!ossl_prov_is_running())
283         return 0;
284
285     ctx = BN_CTX_new_ex(ec_key_get_libctx(ec1));
286     if (ctx == NULL)
287         return 0;
288
289     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
290         ok = ok && group_a != NULL && group_b != NULL
291             && EC_GROUP_cmp(group_a, group_b, ctx) == 0;
292     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
293         const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
294         const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
295
296         ok = ok && BN_cmp(pa, pb) == 0;
297     }
298     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
299         const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
300         const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
301
302         ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
303     }
304     BN_CTX_free(ctx);
305     return ok;
306 }
307
308 static
309 int common_import(void *keydata, int selection, const OSSL_PARAM params[],
310                   int sm2_curve)
311 {
312     EC_KEY *ec = keydata;
313     const EC_GROUP *ecg = NULL;
314     int ok = 1;
315
316     if (!ossl_prov_is_running() || ec == NULL)
317         return 0;
318
319     /*
320      * In this implementation, we can export/import only keydata in the
321      * following combinations:
322      *   - domain parameters (+optional other params)
323      *   - public key with associated domain parameters (+optional other params)
324      *   - private key with associated public key and domain parameters
325      *         (+optional other params)
326      *
327      * This means:
328      *   - domain parameters must always be requested
329      *   - private key must be requested alongside public key
330      *   - other parameters are always optional
331      */
332     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
333         return 0;
334     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
335             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
336         return 0;
337
338     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
339         ok = ok && ec_group_fromdata(ec, params);
340
341     /*
342      * sm2_curve: import the keys or domparams only on SM2 Curve
343      * !sm2_curve: import the keys or domparams only not on SM2 Curve
344      */
345     if ((ecg = EC_KEY_get0_group(ec)) == NULL
346             || (sm2_curve ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
347         return 0;
348
349     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
350         int include_private =
351             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
352
353         ok = ok && ec_key_fromdata(ec, params, include_private);
354     }
355     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
356         ok = ok && ec_key_otherparams_fromdata(ec, params);
357
358     return ok;
359 }
360
361 static
362 int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
363 {
364     return common_import(keydata, selection, params, 0);
365 }
366
367 #ifndef OPENSSL_NO_SM2
368 static
369 int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
370 {
371     return common_import(keydata, selection, params, 1);
372 }
373 #endif
374
375 static
376 int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
377               void *cbarg)
378 {
379     EC_KEY *ec = keydata;
380     OSSL_PARAM_BLD *tmpl = NULL;
381     OSSL_PARAM *params = NULL;
382     unsigned char *pub_key = NULL, *genbuf = NULL;
383     BN_CTX *bnctx = NULL;
384     int ok = 1;
385
386     if (!ossl_prov_is_running() || ec == NULL)
387         return 0;
388
389     /*
390      * In this implementation, we can export/import only keydata in the
391      * following combinations:
392      *   - domain parameters (+optional other params)
393      *   - public key with associated domain parameters (+optional other params)
394      *   - private key with associated public key and domain parameters
395      *         (+optional other params)
396      *
397      * This means:
398      *   - domain parameters must always be requested
399      *   - private key must be requested alongside public key
400      *   - other parameters are always optional
401      */
402     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
403         return 0;
404     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
405             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
406         return 0;
407     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
408             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
409         return 0;
410
411     tmpl = OSSL_PARAM_BLD_new();
412     if (tmpl == NULL)
413         return 0;
414
415     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
416         bnctx = BN_CTX_new_ex(ec_key_get_libctx(ec));
417         if (bnctx == NULL) {
418             ok = 0;
419             goto end;
420         }
421         BN_CTX_start(bnctx);
422         ok = ok && ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
423                                    ec_key_get_libctx(ec), ec_key_get0_propq(ec),
424                                    bnctx, &genbuf);
425     }
426
427     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
428         int include_private =
429             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
430
431         ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
432     }
433     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
434         ok = ok && otherparams_to_params(ec, tmpl, NULL);
435
436     if (ok && (params = OSSL_PARAM_BLD_to_param(tmpl)) != NULL)
437         ok = param_cb(params, cbarg);
438 end:
439     OSSL_PARAM_BLD_free_params(params);
440     OSSL_PARAM_BLD_free(tmpl);
441     OPENSSL_free(pub_key);
442     OPENSSL_free(genbuf);
443     BN_CTX_end(bnctx);
444     BN_CTX_free(bnctx);
445     return ok;
446 }
447
448 /* IMEXPORT = IMPORT + EXPORT */
449
450 # define EC_IMEXPORTABLE_DOM_PARAMETERS                                        \
451     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),               \
452     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),              \
453     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),            \
454     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),                              \
455     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),                              \
456     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),                              \
457     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),            \
458     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),                          \
459     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),                       \
460     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0)
461
462 # define EC_IMEXPORTABLE_PUBLIC_KEY                                            \
463     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
464 # define EC_IMEXPORTABLE_PRIVATE_KEY                                           \
465     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
466 # define EC_IMEXPORTABLE_OTHER_PARAMETERS                                      \
467     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL)
468
469 /*
470  * Include all the possible combinations of OSSL_PARAM arrays for
471  * ec_imexport_types().
472  *
473  * They are in a separate file as it is ~100 lines of unreadable and
474  * uninteresting machine generated stuff.
475  *
476  * TODO(3.0): the generated list looks quite ugly, as to cover all possible
477  * combinations of the bits in `selection`, it also includes combinations that
478  * are not really useful: we might want to consider alternatives to this
479  * solution.
480  */
481 #include "ec_kmgmt_imexport.inc"
482
483 static ossl_inline
484 const OSSL_PARAM *ec_imexport_types(int selection)
485 {
486     int type_select = 0;
487
488     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
489         type_select += 1;
490     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
491         type_select += 2;
492     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
493         type_select += 4;
494     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
495         type_select += 8;
496     return ec_types[type_select];
497 }
498
499 static
500 const OSSL_PARAM *ec_import_types(int selection)
501 {
502     return ec_imexport_types(selection);
503 }
504
505 static
506 const OSSL_PARAM *ec_export_types(int selection)
507 {
508     return ec_imexport_types(selection);
509 }
510
511 static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
512 {
513 #ifdef OPENSSL_NO_EC2M
514     return 1;
515 #else
516     int ret = 0, m;
517     unsigned int k1 = 0, k2 = 0, k3 = 0;
518     int basis_nid;
519     const char *basis_name = NULL;
520     int fid = EC_GROUP_get_field_type(group);
521
522     if (fid != NID_X9_62_characteristic_two_field)
523         return 1;
524
525     basis_nid = EC_GROUP_get_basis_type(group);
526     if (basis_nid == NID_X9_62_tpBasis)
527         basis_name = SN_X9_62_tpBasis;
528     else if (basis_nid == NID_X9_62_ppBasis)
529         basis_name = SN_X9_62_ppBasis;
530     else
531         goto err;
532
533     m = EC_GROUP_get_degree(group);
534     if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
535         || !ossl_param_build_set_utf8_string(NULL, params,
536                                              OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
537                                              basis_name))
538         goto err;
539
540     if (basis_nid == NID_X9_62_tpBasis) {
541         if (!EC_GROUP_get_trinomial_basis(group, &k1)
542             || !ossl_param_build_set_int(NULL, params,
543                                          OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
544                                          (int)k1))
545             goto err;
546     } else {
547         if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
548             || !ossl_param_build_set_int(NULL, params,
549                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
550             || !ossl_param_build_set_int(NULL, params,
551                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
552             || !ossl_param_build_set_int(NULL, params,
553                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
554             goto err;
555     }
556     ret = 1;
557 err:
558     return ret;
559 #endif /* OPENSSL_NO_EC2M */
560 }
561
562 static
563 int common_get_params(void *key, OSSL_PARAM params[], int sm2)
564 {
565     int ret = 0;
566     EC_KEY *eck = key;
567     const EC_GROUP *ecg = NULL;
568     OSSL_PARAM *p;
569     unsigned char *pub_key = NULL, *genbuf = NULL;
570     OPENSSL_CTX *libctx;
571     const char *propq;
572     BN_CTX *bnctx = NULL;
573
574     ecg = EC_KEY_get0_group(eck);
575     if (ecg == NULL)
576         return 0;
577
578     libctx = ec_key_get_libctx(eck);
579     propq = ec_key_get0_propq(eck);
580
581     bnctx = BN_CTX_new_ex(libctx);
582     if (bnctx == NULL)
583         return 0;
584     BN_CTX_start(bnctx);
585
586     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
587         && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
588         goto err;
589     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
590         && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
591         goto err;
592     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
593         int ecbits, sec_bits;
594
595         ecbits = EC_GROUP_order_bits(ecg);
596
597         /*
598          * The following estimates are based on the values published
599          * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
600          * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
601          *
602          * Note that the above reference explicitly categorizes algorithms in a
603          * discrete set of values {80, 112, 128, 192, 256}, and that it is
604          * relevant only for NIST approved Elliptic Curves, while OpenSSL
605          * applies the same logic also to other curves.
606          *
607          * Classifications produced by other standardazing bodies might differ,
608          * so the results provided for "bits of security" by this provider are
609          * to be considered merely indicative, and it is the users'
610          * responsibility to compare these values against the normative
611          * references that may be relevant for their intent and purposes.
612          */
613         if (ecbits >= 512)
614             sec_bits = 256;
615         else if (ecbits >= 384)
616             sec_bits = 192;
617         else if (ecbits >= 256)
618             sec_bits = 128;
619         else if (ecbits >= 224)
620             sec_bits = 112;
621         else if (ecbits >= 160)
622             sec_bits = 80;
623         else
624             sec_bits = ecbits / 2;
625
626         if (!OSSL_PARAM_set_int(p, sec_bits))
627             goto err;
628     }
629
630     if (!sm2) {
631         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
632                 && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
633             goto err;
634     } else {
635         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
636                 && !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
637             goto err;
638     }
639
640     /* SM2 doesn't support this PARAM */
641     if (!sm2) {
642         p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
643         if (p != NULL) {
644             int ecdh_cofactor_mode = 0;
645
646             ecdh_cofactor_mode =
647                 (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
648
649             if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
650                 goto err;
651         }
652     }
653     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT)) != NULL) {
654         p->return_size = EC_POINT_point2oct(EC_KEY_get0_group(key),
655                                             EC_KEY_get0_public_key(key),
656                                             POINT_CONVERSION_UNCOMPRESSED,
657                                             p->data, p->return_size, bnctx);
658         if (p->return_size == 0)
659             goto err;
660     }
661
662     ret = ec_get_ecm_params(ecg, params)
663           && ec_group_todata(ecg, NULL, params, libctx, propq, bnctx, &genbuf)
664           && key_to_params(eck, NULL, params, 1, &pub_key)
665           && otherparams_to_params(eck, NULL, params);
666 err:
667     OPENSSL_free(genbuf);
668     OPENSSL_free(pub_key);
669     BN_CTX_end(bnctx);
670     BN_CTX_free(bnctx);
671     return ret;
672 }
673
674 static
675 int ec_get_params(void *key, OSSL_PARAM params[])
676 {
677     return common_get_params(key, params, 0);
678 }
679
680 #ifndef OPENSSL_NO_EC2M
681 # define EC2M_GETTABLE_DOM_PARAMS                                              \
682         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL),                      \
683         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0),        \
684         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL),               \
685         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL),                  \
686         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL),                  \
687         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
688 #else
689 # define EC2M_GETTABLE_DOM_PARAMS
690 #endif
691
692 static const OSSL_PARAM ec_known_gettable_params[] = {
693     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
694     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
695     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
696     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
697     EC_IMEXPORTABLE_DOM_PARAMETERS,
698     EC2M_GETTABLE_DOM_PARAMS
699     EC_IMEXPORTABLE_PUBLIC_KEY,
700     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
701     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
702     EC_IMEXPORTABLE_PRIVATE_KEY,
703     EC_IMEXPORTABLE_OTHER_PARAMETERS,
704     OSSL_PARAM_END
705 };
706
707 static
708 const OSSL_PARAM *ec_gettable_params(void *provctx)
709 {
710     return ec_known_gettable_params;
711 }
712
713 static const OSSL_PARAM ec_known_settable_params[] = {
714     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
715     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
716     OSSL_PARAM_END
717 };
718
719 static
720 const OSSL_PARAM *ec_settable_params(void *provctx)
721 {
722     return ec_known_settable_params;
723 }
724
725 static
726 int ec_set_params(void *key, const OSSL_PARAM params[])
727 {
728     EC_KEY *eck = key;
729     const OSSL_PARAM *p;
730
731     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT);
732     if (p != NULL) {
733         BN_CTX *ctx = BN_CTX_new_ex(ec_key_get_libctx(key));
734         int ret = 1;
735
736         if (ctx == NULL
737                 || p->data_type != OSSL_PARAM_OCTET_STRING
738                 || !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
739             ret = 0;
740         BN_CTX_free(ctx);
741         if (!ret)
742             return 0;
743     }
744
745     return ec_key_otherparams_fromdata(eck, params);
746 }
747
748 #ifndef OPENSSL_NO_SM2
749 static
750 int sm2_get_params(void *key, OSSL_PARAM params[])
751 {
752     return common_get_params(key, params, 1);
753 }
754
755 static const OSSL_PARAM sm2_known_gettable_params[] = {
756     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
757     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
758     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
759     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
760     EC_IMEXPORTABLE_DOM_PARAMETERS,
761     EC_IMEXPORTABLE_PUBLIC_KEY,
762     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
763     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
764     EC_IMEXPORTABLE_PRIVATE_KEY,
765     OSSL_PARAM_END
766 };
767
768 static
769 const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
770 {
771     return sm2_known_gettable_params;
772 }
773
774 static const OSSL_PARAM sm2_known_settable_params[] = {
775     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
776     OSSL_PARAM_END
777 };
778
779 static
780 const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
781 {
782     return sm2_known_settable_params;
783 }
784 #endif
785
786 static
787 int ec_validate(void *keydata, int selection)
788 {
789     EC_KEY *eck = keydata;
790     int ok = 0;
791     BN_CTX *ctx = NULL;
792
793     if (!ossl_prov_is_running())
794         return 0;
795
796     ctx = BN_CTX_new_ex(ec_key_get_libctx(eck));
797     if  (ctx == NULL)
798         return 0;
799
800     if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
801         ok = 1;
802
803     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
804         ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
805
806     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
807         ok = ok && ec_key_public_check(eck, ctx);
808
809     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
810         ok = ok && ec_key_private_check(eck);
811
812     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
813         ok = ok && ec_key_pairwise_check(eck, ctx);
814
815     BN_CTX_free(ctx);
816     return ok;
817 }
818
819 struct ec_gen_ctx {
820     OPENSSL_CTX *libctx;
821     char *group_name;
822     char *encoding;
823     char *field_type;
824     BIGNUM *p, *a, *b, *order, *cofactor;
825     unsigned char *gen, *seed;
826     size_t gen_len, seed_len;
827     int selection;
828     int ecdh_mode;
829     EC_GROUP *gen_group;
830 };
831
832 static void *ec_gen_init(void *provctx, int selection)
833 {
834     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
835     struct ec_gen_ctx *gctx = NULL;
836
837     if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
838         return NULL;
839
840     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
841         gctx->libctx = libctx;
842         gctx->selection = selection;
843         gctx->ecdh_mode = 0;
844     }
845     return gctx;
846 }
847
848 static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
849 {
850     struct ec_gen_ctx *gctx = genctx;
851     EC_GROUP *group;
852
853     group = EC_GROUP_dup(src);
854     if (group == NULL) {
855         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
856         return 0;
857     }
858     EC_GROUP_free(gctx->gen_group);
859     gctx->gen_group = group;
860     return 1;
861 }
862
863 static int ec_gen_set_template(void *genctx, void *templ)
864 {
865     struct ec_gen_ctx *gctx = genctx;
866     EC_KEY *ec = templ;
867     const EC_GROUP *ec_group;
868
869     if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
870         return 0;
871     if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
872         return 0;
873     return ec_gen_set_group(gctx, ec_group);
874 }
875
876 #define COPY_INT_PARAM(params, key, val)                                       \
877 p = OSSL_PARAM_locate_const(params, key);                                      \
878 if (p != NULL && !OSSL_PARAM_get_int(p, &val))                                 \
879     goto err;
880
881 #define COPY_UTF8_PARAM(params, key, val)                                      \
882 p = OSSL_PARAM_locate_const(params, key);                                      \
883 if (p != NULL) {                                                               \
884     if (p->data_type != OSSL_PARAM_UTF8_STRING)                                \
885         goto err;                                                              \
886     OPENSSL_free(val);                                                         \
887     val = OPENSSL_strdup(p->data);                                             \
888     if (val == NULL)                                                           \
889         goto err;                                                              \
890 }
891
892 #define COPY_OCTET_PARAM(params, key, val, len)                                \
893 p = OSSL_PARAM_locate_const(params, key);                                      \
894 if (p != NULL) {                                                               \
895     if (p->data_type != OSSL_PARAM_OCTET_STRING)                               \
896         goto err;                                                              \
897     OPENSSL_free(val);                                                         \
898     len = p->data_size;                                                        \
899     val = OPENSSL_memdup(p->data, p->data_size);                               \
900     if (val == NULL)                                                           \
901         goto err;                                                              \
902 }
903
904 #define COPY_BN_PARAM(params, key, bn)                                         \
905 p = OSSL_PARAM_locate_const(params, key);                                      \
906 if (p != NULL) {                                                               \
907     if (bn == NULL)                                                            \
908         bn = BN_new();                                                         \
909     if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn))                              \
910         goto err;                                                              \
911 }
912
913 static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
914 {
915     int ret = 0;
916     struct ec_gen_ctx *gctx = genctx;
917     const OSSL_PARAM *p;
918     EC_GROUP *group = NULL;
919
920     COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
921
922     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
923     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
924     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
925
926     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
927     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
928     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
929     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
930     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
931
932     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
933     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
934                      gctx->gen_len);
935
936     ret = 1;
937 err:
938     EC_GROUP_free(group);
939     return ret;
940 }
941
942 static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
943 {
944     int ret = 0;
945     OSSL_PARAM_BLD *bld;
946     OSSL_PARAM *params = NULL;
947     EC_GROUP *group = NULL;
948
949     bld = OSSL_PARAM_BLD_new();
950     if (bld == NULL)
951         return 0;
952
953     if (gctx->encoding != NULL
954         && !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
955                                             gctx->encoding, 0))
956         goto err;
957
958     if (gctx->group_name != NULL) {
959         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
960                                              gctx->group_name, 0))
961             goto err;
962         /* Ignore any other parameters if there is a group name */
963         goto build;
964     } else if (gctx->field_type != NULL) {
965         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
966                                              gctx->field_type, 0))
967             goto err;
968     } else {
969         goto err;
970     }
971     if (gctx->p == NULL
972         || gctx->a == NULL
973         || gctx->b == NULL
974         || gctx->order == NULL
975         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
976         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
977         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
978         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
979         goto err;
980
981     if (gctx->cofactor != NULL
982         && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
983                                    gctx->cofactor))
984         goto err;
985
986     if (gctx->seed != NULL
987         && !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
988                                              gctx->seed, gctx->seed_len))
989         goto err;
990
991     if (gctx->gen == NULL
992         || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
993                                              gctx->gen, gctx->gen_len))
994         goto err;
995 build:
996     params = OSSL_PARAM_BLD_to_param(bld);
997     if (params == NULL)
998         goto err;
999     group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
1000     if (group == NULL)
1001         goto err;
1002
1003     EC_GROUP_free(gctx->gen_group);
1004     gctx->gen_group = group;
1005
1006     ret = 1;
1007 err:
1008     OSSL_PARAM_BLD_free_params(params);
1009     OSSL_PARAM_BLD_free(bld);
1010     return ret;
1011 }
1012
1013 static const OSSL_PARAM *ec_gen_settable_params(void *provctx)
1014 {
1015     static OSSL_PARAM settable[] = {
1016         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
1017         OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
1018         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
1019         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
1020         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
1021         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
1022         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
1023         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
1024         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
1025         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
1026         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
1027         OSSL_PARAM_END
1028     };
1029
1030     return settable;
1031 }
1032
1033 static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
1034 {
1035     if (group == NULL) {
1036         ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
1037         return 0;
1038     }
1039     return EC_KEY_set_group(ec, group) > 0;
1040 }
1041
1042 /*
1043  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1044  */
1045 static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1046 {
1047     struct ec_gen_ctx *gctx = genctx;
1048     EC_KEY *ec = NULL;
1049     int ret = 0;
1050
1051     if (!ossl_prov_is_running()
1052         || gctx == NULL
1053         || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1054         return NULL;
1055
1056     if (gctx->gen_group == NULL) {
1057         if (!ec_gen_set_group_from_params(gctx))
1058             goto err;
1059     } else {
1060         if (gctx->encoding) {
1061             int flags = ec_encoding_name2id(gctx->encoding);
1062             if (flags < 0)
1063                 goto err;
1064             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1065         }
1066     }
1067
1068     /* We must always assign a group, no matter what */
1069     ret = ec_gen_assign_group(ec, gctx->gen_group);
1070
1071     /* Whether you want it or not, you get a keypair, not just one half */
1072     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
1073         ret = ret && EC_KEY_generate_key(ec);
1074
1075     if (gctx->ecdh_mode != -1)
1076         ret = ret && ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
1077
1078     if (ret)
1079         return ec;
1080 err:
1081     /* Something went wrong, throw the key away */
1082     EC_KEY_free(ec);
1083     return NULL;
1084 }
1085
1086 #ifndef OPENSSL_NO_SM2
1087 /*
1088  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1089  */
1090 static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1091 {
1092     struct ec_gen_ctx *gctx = genctx;
1093     EC_KEY *ec = NULL;
1094     int ret = 1;
1095
1096     if (gctx == NULL
1097         || (ec = EC_KEY_new_with_libctx(gctx->libctx, NULL)) == NULL)
1098         return NULL;
1099
1100     if (gctx->gen_group == NULL) {
1101         if (!ec_gen_set_group_from_params(gctx))
1102             goto err;
1103     } else {
1104         if (gctx->encoding) {
1105             int flags = ec_encoding_name2id(gctx->encoding);
1106             if (flags < 0)
1107                 goto err;
1108             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1109         }
1110     }
1111
1112     /* We must always assign a group, no matter what */
1113     ret = ec_gen_assign_group(ec, gctx->gen_group);
1114
1115     /* Whether you want it or not, you get a keypair, not just one half */
1116     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
1117         /*
1118          * For SM2, we need a new flag to indicate the 'generate' function
1119          * to use a new range
1120          */
1121         EC_KEY_set_flags(ec, EC_FLAG_SM2_RANGE);
1122         ret = ret && EC_KEY_generate_key(ec);
1123     }
1124
1125     if (ret)
1126         return ec;
1127 err:
1128     /* Something went wrong, throw the key away */
1129     EC_KEY_free(ec);
1130     return NULL;
1131 }
1132 #endif
1133
1134 static void ec_gen_cleanup(void *genctx)
1135 {
1136     struct ec_gen_ctx *gctx = genctx;
1137
1138     if (gctx == NULL)
1139         return;
1140
1141     EC_GROUP_free(gctx->gen_group);
1142     BN_free(gctx->p);
1143     BN_free(gctx->a);
1144     BN_free(gctx->b);
1145     BN_free(gctx->order);
1146     BN_free(gctx->cofactor);
1147     OPENSSL_free(gctx->group_name);
1148     OPENSSL_free(gctx->field_type);;
1149     OPENSSL_free(gctx->encoding);
1150     OPENSSL_free(gctx->seed);
1151     OPENSSL_free(gctx->gen);
1152     OPENSSL_free(gctx);
1153 }
1154
1155 void *ec_load(const void *reference, size_t reference_sz)
1156 {
1157     EC_KEY *ec = NULL;
1158
1159     if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
1160         /* The contents of the reference is the address to our object */
1161         ec = *(EC_KEY **)reference;
1162         /* We grabbed, so we detach it */
1163         *(EC_KEY **)reference = NULL;
1164         return ec;
1165     }
1166     return NULL;
1167 }
1168
1169 const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
1170     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1171     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1172     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1173       (void (*)(void))ec_gen_set_template },
1174     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1175     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1176       (void (*)(void))ec_gen_settable_params },
1177     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
1178     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1179     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
1180     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1181     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
1182     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
1183     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1184     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
1185     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1186     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1187     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
1188     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
1189     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1190     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1191     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1192     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1193       (void (*)(void))ec_query_operation_name },
1194     { 0, NULL }
1195 };
1196
1197 #ifndef OPENSSL_NO_SM2
1198 const OSSL_DISPATCH sm2_keymgmt_functions[] = {
1199     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1200     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1201     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1202       (void (*)(void))ec_gen_set_template },
1203     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1204     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1205       (void (*)(void))ec_gen_settable_params },
1206     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
1207     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1208     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1209     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
1210     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
1211     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1212     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
1213     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1214     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1215     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
1216     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
1217     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1218     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1219     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1220     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1221       (void (*)(void))sm2_query_operation_name },
1222     { 0, NULL }
1223 };
1224 #endif