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