Update copyright year
[openssl.git] / providers / implementations / keymgmt / ec_kmgmt.c
1 /*
2  * Copyright 2020-2021 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, group_check = 0;
233     const char *name = NULL;
234     point_conversion_form_t format;
235
236     if (ec == NULL)
237         return 0;
238
239     format = EC_KEY_get_conv_form(ec);
240     name = ec_pt_format_id2name((int)format);
241     if (name != NULL
242         && !ossl_param_build_set_utf8_string(tmpl, params,
243                                              OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
244                                              name))
245         return 0;
246
247     group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;
248     name = ec_check_group_type_id2name(group_check);
249     if (name != NULL
250         && !ossl_param_build_set_utf8_string(tmpl, params,
251                                              OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
252                                              name))
253         return 0;
254
255     if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0)
256         ossl_param_build_set_int(tmpl, params,
257                                  OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0);
258
259     ecdh_cofactor_mode =
260         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
261     return ossl_param_build_set_int(tmpl, params,
262                                     OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
263                                     ecdh_cofactor_mode);
264 }
265
266 static
267 void *ec_newdata(void *provctx)
268 {
269     if (!ossl_prov_is_running())
270         return NULL;
271     return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);
272 }
273
274 static
275 void ec_freedata(void *keydata)
276 {
277     EC_KEY_free(keydata);
278 }
279
280 static
281 int ec_has(const void *keydata, int selection)
282 {
283     const EC_KEY *ec = keydata;
284     int ok = 0;
285
286     if (ossl_prov_is_running() && ec != NULL) {
287         if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
288             ok = 1;
289
290         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
291             ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
292         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
293             ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
294         if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
295             ok = ok && (EC_KEY_get0_group(ec) != NULL);
296         /*
297          * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
298          * available, so no extra check is needed other than the previous one
299          * against EC_POSSIBLE_SELECTIONS.
300          */
301     }
302     return ok;
303 }
304
305 static int ec_match(const void *keydata1, const void *keydata2, int selection)
306 {
307     const EC_KEY *ec1 = keydata1;
308     const EC_KEY *ec2 = keydata2;
309     const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
310     const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
311     BN_CTX *ctx = NULL;
312     int ok = 1;
313
314     if (!ossl_prov_is_running())
315         return 0;
316
317     ctx = BN_CTX_new_ex(ec_key_get_libctx(ec1));
318     if (ctx == NULL)
319         return 0;
320
321     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
322         ok = ok && group_a != NULL && group_b != NULL
323             && EC_GROUP_cmp(group_a, group_b, ctx) == 0;
324     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
325         const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
326         const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
327
328         ok = ok && BN_cmp(pa, pb) == 0;
329     }
330     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
331         const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
332         const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
333
334         ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
335     }
336     BN_CTX_free(ctx);
337     return ok;
338 }
339
340 static
341 int common_import(void *keydata, int selection, const OSSL_PARAM params[],
342                   int sm2_curve)
343 {
344     EC_KEY *ec = keydata;
345     const EC_GROUP *ecg = NULL;
346     int ok = 1;
347
348     if (!ossl_prov_is_running() || ec == NULL)
349         return 0;
350
351     /*
352      * In this implementation, we can export/import only keydata in the
353      * following combinations:
354      *   - domain parameters (+optional other params)
355      *   - public key with associated domain parameters (+optional other params)
356      *   - private key with associated public key and domain parameters
357      *         (+optional other params)
358      *
359      * This means:
360      *   - domain parameters must always be requested
361      *   - private key must be requested alongside public key
362      *   - other parameters are always optional
363      */
364     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
365         return 0;
366     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
367             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
368         return 0;
369
370     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
371         ok = ok && ec_group_fromdata(ec, params);
372
373     /*
374      * sm2_curve: import the keys or domparams only on SM2 Curve
375      * !sm2_curve: import the keys or domparams only not on SM2 Curve
376      */
377     if ((ecg = EC_KEY_get0_group(ec)) == NULL
378             || (sm2_curve ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
379         return 0;
380
381     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
382         int include_private =
383             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
384
385         ok = ok && ec_key_fromdata(ec, params, include_private);
386     }
387     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
388         ok = ok && ec_key_otherparams_fromdata(ec, params);
389
390     return ok;
391 }
392
393 static
394 int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
395 {
396     return common_import(keydata, selection, params, 0);
397 }
398
399 #ifndef FIPS_MODULE
400 # ifndef OPENSSL_NO_SM2
401 static
402 int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
403 {
404     return common_import(keydata, selection, params, 1);
405 }
406 # endif
407 #endif
408
409 static
410 int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
411               void *cbarg)
412 {
413     EC_KEY *ec = keydata;
414     OSSL_PARAM_BLD *tmpl = NULL;
415     OSSL_PARAM *params = NULL;
416     unsigned char *pub_key = NULL, *genbuf = NULL;
417     BN_CTX *bnctx = NULL;
418     int ok = 1;
419
420     if (!ossl_prov_is_running() || ec == NULL)
421         return 0;
422
423     /*
424      * In this implementation, we can export/import only keydata in the
425      * following combinations:
426      *   - domain parameters (+optional other params)
427      *   - public key with associated domain parameters (+optional other params)
428      *   - private key with associated public key and domain parameters
429      *         (+optional other params)
430      *
431      * This means:
432      *   - domain parameters must always be requested
433      *   - private key must be requested alongside public key
434      *   - other parameters are always optional
435      */
436     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
437         return 0;
438     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
439             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
440         return 0;
441     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
442             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
443         return 0;
444
445     tmpl = OSSL_PARAM_BLD_new();
446     if (tmpl == NULL)
447         return 0;
448
449     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
450         bnctx = BN_CTX_new_ex(ec_key_get_libctx(ec));
451         if (bnctx == NULL) {
452             ok = 0;
453             goto end;
454         }
455         BN_CTX_start(bnctx);
456         ok = ok && ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
457                                    ec_key_get_libctx(ec), ec_key_get0_propq(ec),
458                                    bnctx, &genbuf);
459     }
460
461     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
462         int include_private =
463             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
464
465         ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
466     }
467     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
468         ok = ok && otherparams_to_params(ec, tmpl, NULL);
469
470     if (ok && (params = OSSL_PARAM_BLD_to_param(tmpl)) != NULL)
471         ok = param_cb(params, cbarg);
472 end:
473     OSSL_PARAM_BLD_free_params(params);
474     OSSL_PARAM_BLD_free(tmpl);
475     OPENSSL_free(pub_key);
476     OPENSSL_free(genbuf);
477     BN_CTX_end(bnctx);
478     BN_CTX_free(bnctx);
479     return ok;
480 }
481
482 /* IMEXPORT = IMPORT + EXPORT */
483
484 # define EC_IMEXPORTABLE_DOM_PARAMETERS                                        \
485     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),               \
486     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),              \
487     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),\
488     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),            \
489     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),                              \
490     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),                              \
491     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),                              \
492     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),            \
493     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),                          \
494     OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),                       \
495     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0)
496
497 # define EC_IMEXPORTABLE_PUBLIC_KEY                                            \
498     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
499 # define EC_IMEXPORTABLE_PRIVATE_KEY                                           \
500     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
501 # define EC_IMEXPORTABLE_OTHER_PARAMETERS                                      \
502     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),                   \
503     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)
504
505 /*
506  * Include all the possible combinations of OSSL_PARAM arrays for
507  * ec_imexport_types().
508  *
509  * They are in a separate file as it is ~100 lines of unreadable and
510  * uninteresting machine generated stuff.
511  */
512 #include "ec_kmgmt_imexport.inc"
513
514 static ossl_inline
515 const OSSL_PARAM *ec_imexport_types(int selection)
516 {
517     int type_select = 0;
518
519     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
520         type_select += 1;
521     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
522         type_select += 2;
523     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
524         type_select += 4;
525     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
526         type_select += 8;
527     return ec_types[type_select];
528 }
529
530 static
531 const OSSL_PARAM *ec_import_types(int selection)
532 {
533     return ec_imexport_types(selection);
534 }
535
536 static
537 const OSSL_PARAM *ec_export_types(int selection)
538 {
539     return ec_imexport_types(selection);
540 }
541
542 static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
543 {
544 #ifdef OPENSSL_NO_EC2M
545     return 1;
546 #else
547     int ret = 0, m;
548     unsigned int k1 = 0, k2 = 0, k3 = 0;
549     int basis_nid;
550     const char *basis_name = NULL;
551     int fid = EC_GROUP_get_field_type(group);
552
553     if (fid != NID_X9_62_characteristic_two_field)
554         return 1;
555
556     basis_nid = EC_GROUP_get_basis_type(group);
557     if (basis_nid == NID_X9_62_tpBasis)
558         basis_name = SN_X9_62_tpBasis;
559     else if (basis_nid == NID_X9_62_ppBasis)
560         basis_name = SN_X9_62_ppBasis;
561     else
562         goto err;
563
564     m = EC_GROUP_get_degree(group);
565     if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
566         || !ossl_param_build_set_utf8_string(NULL, params,
567                                              OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
568                                              basis_name))
569         goto err;
570
571     if (basis_nid == NID_X9_62_tpBasis) {
572         if (!EC_GROUP_get_trinomial_basis(group, &k1)
573             || !ossl_param_build_set_int(NULL, params,
574                                          OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
575                                          (int)k1))
576             goto err;
577     } else {
578         if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
579             || !ossl_param_build_set_int(NULL, params,
580                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
581             || !ossl_param_build_set_int(NULL, params,
582                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
583             || !ossl_param_build_set_int(NULL, params,
584                                          OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
585             goto err;
586     }
587     ret = 1;
588 err:
589     return ret;
590 #endif /* OPENSSL_NO_EC2M */
591 }
592
593 static
594 int common_get_params(void *key, OSSL_PARAM params[], int sm2)
595 {
596     int ret = 0;
597     EC_KEY *eck = key;
598     const EC_GROUP *ecg = NULL;
599     OSSL_PARAM *p;
600     unsigned char *pub_key = NULL, *genbuf = NULL;
601     OSSL_LIB_CTX *libctx;
602     const char *propq;
603     BN_CTX *bnctx = NULL;
604
605     ecg = EC_KEY_get0_group(eck);
606     if (ecg == NULL)
607         return 0;
608
609     libctx = ec_key_get_libctx(eck);
610     propq = ec_key_get0_propq(eck);
611
612     bnctx = BN_CTX_new_ex(libctx);
613     if (bnctx == NULL)
614         return 0;
615     BN_CTX_start(bnctx);
616
617     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
618         && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
619         goto err;
620     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
621         && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
622         goto err;
623     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
624         int ecbits, sec_bits;
625
626         ecbits = EC_GROUP_order_bits(ecg);
627
628         /*
629          * The following estimates are based on the values published
630          * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
631          * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
632          *
633          * Note that the above reference explicitly categorizes algorithms in a
634          * discrete set of values {80, 112, 128, 192, 256}, and that it is
635          * relevant only for NIST approved Elliptic Curves, while OpenSSL
636          * applies the same logic also to other curves.
637          *
638          * Classifications produced by other standardazing bodies might differ,
639          * so the results provided for "bits of security" by this provider are
640          * to be considered merely indicative, and it is the users'
641          * responsibility to compare these values against the normative
642          * references that may be relevant for their intent and purposes.
643          */
644         if (ecbits >= 512)
645             sec_bits = 256;
646         else if (ecbits >= 384)
647             sec_bits = 192;
648         else if (ecbits >= 256)
649             sec_bits = 128;
650         else if (ecbits >= 224)
651             sec_bits = 112;
652         else if (ecbits >= 160)
653             sec_bits = 80;
654         else
655             sec_bits = ecbits / 2;
656
657         if (!OSSL_PARAM_set_int(p, sec_bits))
658             goto err;
659     }
660
661     if (!sm2) {
662         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
663                 && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
664             goto err;
665     } else {
666         if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
667                 && !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
668             goto err;
669     }
670
671     /* SM2 doesn't support this PARAM */
672     if (!sm2) {
673         p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
674         if (p != NULL) {
675             int ecdh_cofactor_mode = 0;
676
677             ecdh_cofactor_mode =
678                 (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
679
680             if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
681                 goto err;
682         }
683     }
684     if ((p = OSSL_PARAM_locate(params,
685                                OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
686         p->return_size = EC_POINT_point2oct(EC_KEY_get0_group(key),
687                                             EC_KEY_get0_public_key(key),
688                                             POINT_CONVERSION_UNCOMPRESSED,
689                                             p->data, p->return_size, bnctx);
690         if (p->return_size == 0)
691             goto err;
692     }
693
694     ret = ec_get_ecm_params(ecg, params)
695           && ec_group_todata(ecg, NULL, params, libctx, propq, bnctx, &genbuf)
696           && key_to_params(eck, NULL, params, 1, &pub_key)
697           && otherparams_to_params(eck, NULL, params);
698 err:
699     OPENSSL_free(genbuf);
700     OPENSSL_free(pub_key);
701     BN_CTX_end(bnctx);
702     BN_CTX_free(bnctx);
703     return ret;
704 }
705
706 static
707 int ec_get_params(void *key, OSSL_PARAM params[])
708 {
709     return common_get_params(key, params, 0);
710 }
711
712 #ifndef OPENSSL_NO_EC2M
713 # define EC2M_GETTABLE_DOM_PARAMS                                              \
714         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL),                      \
715         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0),        \
716         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL),               \
717         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL),                  \
718         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL),                  \
719         OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
720 #else
721 # define EC2M_GETTABLE_DOM_PARAMS
722 #endif
723
724 static const OSSL_PARAM ec_known_gettable_params[] = {
725     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
726     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
727     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
728     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
729     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
730     EC_IMEXPORTABLE_DOM_PARAMETERS,
731     EC2M_GETTABLE_DOM_PARAMS
732     EC_IMEXPORTABLE_PUBLIC_KEY,
733     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
734     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
735     EC_IMEXPORTABLE_PRIVATE_KEY,
736     EC_IMEXPORTABLE_OTHER_PARAMETERS,
737     OSSL_PARAM_END
738 };
739
740 static
741 const OSSL_PARAM *ec_gettable_params(void *provctx)
742 {
743     return ec_known_gettable_params;
744 }
745
746 static const OSSL_PARAM ec_known_settable_params[] = {
747     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
748     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
749     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
750     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
751     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
752     OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),
753     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),
754     OSSL_PARAM_END
755 };
756
757 static
758 const OSSL_PARAM *ec_settable_params(void *provctx)
759 {
760     return ec_known_settable_params;
761 }
762
763 static
764 int ec_set_params(void *key, const OSSL_PARAM params[])
765 {
766     EC_KEY *eck = key;
767     const OSSL_PARAM *p;
768
769     if (key == NULL)
770         return 0;
771
772     if (!ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))
773         return 0;
774
775     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
776     if (p != NULL) {
777         BN_CTX *ctx = BN_CTX_new_ex(ec_key_get_libctx(key));
778         int ret = 1;
779
780         if (ctx == NULL
781                 || p->data_type != OSSL_PARAM_OCTET_STRING
782                 || !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
783             ret = 0;
784         BN_CTX_free(ctx);
785         if (!ret)
786             return 0;
787     }
788
789     return ec_key_otherparams_fromdata(eck, params);
790 }
791
792 #ifndef FIPS_MODULE
793 # ifndef OPENSSL_NO_SM2
794 static
795 int sm2_get_params(void *key, OSSL_PARAM params[])
796 {
797     return common_get_params(key, params, 1);
798 }
799
800 static const OSSL_PARAM sm2_known_gettable_params[] = {
801     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
802     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
803     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
804     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
805     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
806     EC_IMEXPORTABLE_DOM_PARAMETERS,
807     EC_IMEXPORTABLE_PUBLIC_KEY,
808     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
809     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
810     EC_IMEXPORTABLE_PRIVATE_KEY,
811     OSSL_PARAM_END
812 };
813
814 static
815 const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
816 {
817     return sm2_known_gettable_params;
818 }
819
820 static const OSSL_PARAM sm2_known_settable_params[] = {
821     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
822     OSSL_PARAM_END
823 };
824
825 static
826 const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
827 {
828     return sm2_known_settable_params;
829 }
830
831 static
832 int sm2_validate(const void *keydata, int selection)
833 {
834     const EC_KEY *eck = keydata;
835     int ok = 0;
836     BN_CTX *ctx = NULL;
837
838     if (!ossl_prov_is_running())
839         return 0;
840
841     ctx = BN_CTX_new_ex(ec_key_get_libctx(eck));
842     if  (ctx == NULL)
843         return 0;
844
845     if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
846         ok = 1;
847
848     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
849         ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
850
851     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
852         ok = ok && ec_key_public_check(eck, ctx);
853
854     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
855         ok = ok && sm2_key_private_check(eck);
856
857     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
858         ok = ok && ec_key_pairwise_check(eck, ctx);
859
860     BN_CTX_free(ctx);
861     return ok;
862 }
863 # endif
864 #endif
865
866 static
867 int ec_validate(const void *keydata, int selection)
868 {
869     const EC_KEY *eck = keydata;
870     int ok = 0;
871     BN_CTX *ctx = NULL;
872
873     if (!ossl_prov_is_running())
874         return 0;
875
876     ctx = BN_CTX_new_ex(ec_key_get_libctx(eck));
877     if  (ctx == NULL)
878         return 0;
879
880     if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
881         ok = 1;
882
883     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
884         int flags = EC_KEY_get_flags(eck);
885
886         if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)
887             ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck),
888                            (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx);
889         else
890             ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
891     }
892
893     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
894         ok = ok && ec_key_public_check(eck, ctx);
895
896     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
897         ok = ok && ec_key_private_check(eck);
898
899     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
900         ok = ok && ec_key_pairwise_check(eck, ctx);
901
902     BN_CTX_free(ctx);
903     return ok;
904 }
905
906 struct ec_gen_ctx {
907     OSSL_LIB_CTX *libctx;
908     char *group_name;
909     char *encoding;
910     char *pt_format;
911     char *group_check;
912     char *field_type;
913     BIGNUM *p, *a, *b, *order, *cofactor;
914     unsigned char *gen, *seed;
915     size_t gen_len, seed_len;
916     int selection;
917     int ecdh_mode;
918     EC_GROUP *gen_group;
919 };
920
921 static void *ec_gen_init(void *provctx, int selection)
922 {
923     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
924     struct ec_gen_ctx *gctx = NULL;
925
926     if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
927         return NULL;
928
929     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
930         gctx->libctx = libctx;
931         gctx->selection = selection;
932         gctx->ecdh_mode = 0;
933     }
934     return gctx;
935 }
936
937 static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
938 {
939     struct ec_gen_ctx *gctx = genctx;
940     EC_GROUP *group;
941
942     group = EC_GROUP_dup(src);
943     if (group == NULL) {
944         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
945         return 0;
946     }
947     EC_GROUP_free(gctx->gen_group);
948     gctx->gen_group = group;
949     return 1;
950 }
951
952 static int ec_gen_set_template(void *genctx, void *templ)
953 {
954     struct ec_gen_ctx *gctx = genctx;
955     EC_KEY *ec = templ;
956     const EC_GROUP *ec_group;
957
958     if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
959         return 0;
960     if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
961         return 0;
962     return ec_gen_set_group(gctx, ec_group);
963 }
964
965 #define COPY_INT_PARAM(params, key, val)                                       \
966 p = OSSL_PARAM_locate_const(params, key);                                      \
967 if (p != NULL && !OSSL_PARAM_get_int(p, &val))                                 \
968     goto err;
969
970 #define COPY_UTF8_PARAM(params, key, val)                                      \
971 p = OSSL_PARAM_locate_const(params, key);                                      \
972 if (p != NULL) {                                                               \
973     if (p->data_type != OSSL_PARAM_UTF8_STRING)                                \
974         goto err;                                                              \
975     OPENSSL_free(val);                                                         \
976     val = OPENSSL_strdup(p->data);                                             \
977     if (val == NULL)                                                           \
978         goto err;                                                              \
979 }
980
981 #define COPY_OCTET_PARAM(params, key, val, len)                                \
982 p = OSSL_PARAM_locate_const(params, key);                                      \
983 if (p != NULL) {                                                               \
984     if (p->data_type != OSSL_PARAM_OCTET_STRING)                               \
985         goto err;                                                              \
986     OPENSSL_free(val);                                                         \
987     len = p->data_size;                                                        \
988     val = OPENSSL_memdup(p->data, p->data_size);                               \
989     if (val == NULL)                                                           \
990         goto err;                                                              \
991 }
992
993 #define COPY_BN_PARAM(params, key, bn)                                         \
994 p = OSSL_PARAM_locate_const(params, key);                                      \
995 if (p != NULL) {                                                               \
996     if (bn == NULL)                                                            \
997         bn = BN_new();                                                         \
998     if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn))                              \
999         goto err;                                                              \
1000 }
1001
1002 static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
1003 {
1004     int ret = 0;
1005     struct ec_gen_ctx *gctx = genctx;
1006     const OSSL_PARAM *p;
1007     EC_GROUP *group = NULL;
1008
1009     COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
1010
1011     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
1012     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
1013     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
1014     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);
1015     COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);
1016
1017     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
1018     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
1019     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
1020     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
1021     COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
1022
1023     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
1024     COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
1025                      gctx->gen_len);
1026
1027     ret = 1;
1028 err:
1029     EC_GROUP_free(group);
1030     return ret;
1031 }
1032
1033 static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
1034 {
1035     int ret = 0;
1036     OSSL_PARAM_BLD *bld;
1037     OSSL_PARAM *params = NULL;
1038     EC_GROUP *group = NULL;
1039
1040     bld = OSSL_PARAM_BLD_new();
1041     if (bld == NULL)
1042         return 0;
1043
1044     if (gctx->encoding != NULL
1045         && !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
1046                                             gctx->encoding, 0))
1047         goto err;
1048
1049     if (gctx->pt_format != NULL
1050         && !OSSL_PARAM_BLD_push_utf8_string(bld,
1051                                             OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
1052                                             gctx->pt_format, 0))
1053         goto err;
1054
1055     if (gctx->group_name != NULL) {
1056         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
1057                                              gctx->group_name, 0))
1058             goto err;
1059         /* Ignore any other parameters if there is a group name */
1060         goto build;
1061     } else if (gctx->field_type != NULL) {
1062         if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
1063                                              gctx->field_type, 0))
1064             goto err;
1065     } else {
1066         goto err;
1067     }
1068     if (gctx->p == NULL
1069         || gctx->a == NULL
1070         || gctx->b == NULL
1071         || gctx->order == NULL
1072         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
1073         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
1074         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
1075         || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
1076         goto err;
1077
1078     if (gctx->cofactor != NULL
1079         && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
1080                                    gctx->cofactor))
1081         goto err;
1082
1083     if (gctx->seed != NULL
1084         && !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
1085                                              gctx->seed, gctx->seed_len))
1086         goto err;
1087
1088     if (gctx->gen == NULL
1089         || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
1090                                              gctx->gen, gctx->gen_len))
1091         goto err;
1092 build:
1093     params = OSSL_PARAM_BLD_to_param(bld);
1094     if (params == NULL)
1095         goto err;
1096     group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
1097     if (group == NULL)
1098         goto err;
1099
1100     EC_GROUP_free(gctx->gen_group);
1101     gctx->gen_group = group;
1102
1103     ret = 1;
1104 err:
1105     OSSL_PARAM_BLD_free_params(params);
1106     OSSL_PARAM_BLD_free(bld);
1107     return ret;
1108 }
1109
1110 static const OSSL_PARAM *ec_gen_settable_params(void *provctx)
1111 {
1112     static OSSL_PARAM settable[] = {
1113         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
1114         OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
1115         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
1116         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
1117         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
1118         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
1119         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
1120         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
1121         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
1122         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
1123         OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
1124         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
1125         OSSL_PARAM_END
1126     };
1127
1128     return settable;
1129 }
1130
1131 static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
1132 {
1133     if (group == NULL) {
1134         ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
1135         return 0;
1136     }
1137     return EC_KEY_set_group(ec, group) > 0;
1138 }
1139
1140 /*
1141  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1142  */
1143 static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1144 {
1145     struct ec_gen_ctx *gctx = genctx;
1146     EC_KEY *ec = NULL;
1147     int ret = 0;
1148
1149     if (!ossl_prov_is_running()
1150         || gctx == NULL
1151         || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1152         return NULL;
1153
1154     if (gctx->gen_group == NULL) {
1155         if (!ec_gen_set_group_from_params(gctx))
1156             goto err;
1157     } else {
1158         if (gctx->encoding != NULL) {
1159             int flags = ec_encoding_name2id(gctx->encoding);
1160
1161             if (flags < 0)
1162                 goto err;
1163             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1164         }
1165         if (gctx->pt_format != NULL) {
1166             int format = ec_pt_format_name2id(gctx->pt_format);
1167
1168             if (format < 0)
1169                 goto err;
1170             EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1171         }
1172     }
1173
1174     /* We must always assign a group, no matter what */
1175     ret = ec_gen_assign_group(ec, gctx->gen_group);
1176
1177     /* Whether you want it or not, you get a keypair, not just one half */
1178     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
1179         ret = ret && EC_KEY_generate_key(ec);
1180
1181     if (gctx->ecdh_mode != -1)
1182         ret = ret && ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
1183
1184     if (gctx->group_check != NULL)
1185         ret = ret && ec_set_check_group_type_from_name(ec, gctx->group_check);
1186     if (ret)
1187         return ec;
1188 err:
1189     /* Something went wrong, throw the key away */
1190     EC_KEY_free(ec);
1191     return NULL;
1192 }
1193
1194 #ifndef FIPS_MODULE
1195 # ifndef OPENSSL_NO_SM2
1196 /*
1197  * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1198  */
1199 static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1200 {
1201     struct ec_gen_ctx *gctx = genctx;
1202     EC_KEY *ec = NULL;
1203     int ret = 1;
1204
1205     if (gctx == NULL
1206         || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1207         return NULL;
1208
1209     if (gctx->gen_group == NULL) {
1210         if (!ec_gen_set_group_from_params(gctx))
1211             goto err;
1212     } else {
1213         if (gctx->encoding) {
1214             int flags = ec_encoding_name2id(gctx->encoding);
1215
1216             if (flags < 0)
1217                 goto err;
1218             EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1219         }
1220         if (gctx->pt_format != NULL) {
1221             int format = ec_pt_format_name2id(gctx->pt_format);
1222
1223             if (format < 0)
1224                 goto err;
1225             EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1226         }
1227     }
1228
1229     /* We must always assign a group, no matter what */
1230     ret = ec_gen_assign_group(ec, gctx->gen_group);
1231
1232     /* Whether you want it or not, you get a keypair, not just one half */
1233     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
1234         /*
1235          * For SM2, we need a new flag to indicate the 'generate' function
1236          * to use a new range
1237          */
1238         EC_KEY_set_flags(ec, EC_FLAG_SM2_RANGE);
1239         ret = ret && EC_KEY_generate_key(ec);
1240     }
1241
1242     if (ret)
1243         return ec;
1244 err:
1245     /* Something went wrong, throw the key away */
1246     EC_KEY_free(ec);
1247     return NULL;
1248 }
1249 # endif
1250 #endif
1251
1252 static void ec_gen_cleanup(void *genctx)
1253 {
1254     struct ec_gen_ctx *gctx = genctx;
1255
1256     if (gctx == NULL)
1257         return;
1258
1259     EC_GROUP_free(gctx->gen_group);
1260     BN_free(gctx->p);
1261     BN_free(gctx->a);
1262     BN_free(gctx->b);
1263     BN_free(gctx->order);
1264     BN_free(gctx->cofactor);
1265     OPENSSL_free(gctx->group_name);
1266     OPENSSL_free(gctx->field_type);
1267     OPENSSL_free(gctx->pt_format);
1268     OPENSSL_free(gctx->encoding);
1269     OPENSSL_free(gctx->seed);
1270     OPENSSL_free(gctx->gen);
1271     OPENSSL_free(gctx);
1272 }
1273
1274 void *ec_load(const void *reference, size_t reference_sz)
1275 {
1276     EC_KEY *ec = NULL;
1277
1278     if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
1279         /* The contents of the reference is the address to our object */
1280         ec = *(EC_KEY **)reference;
1281         /* We grabbed, so we detach it */
1282         *(EC_KEY **)reference = NULL;
1283         return ec;
1284     }
1285     return NULL;
1286 }
1287
1288 const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
1289     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1290     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1291     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1292       (void (*)(void))ec_gen_set_template },
1293     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1294     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1295       (void (*)(void))ec_gen_settable_params },
1296     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
1297     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1298     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
1299     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1300     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
1301     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
1302     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1303     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
1304     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1305     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1306     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
1307     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
1308     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1309     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1310     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1311     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1312       (void (*)(void))ec_query_operation_name },
1313     { 0, NULL }
1314 };
1315
1316 #ifndef FIPS_MODULE
1317 # ifndef OPENSSL_NO_SM2
1318 const OSSL_DISPATCH sm2_keymgmt_functions[] = {
1319     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1320     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1321     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1322       (void (*)(void))ec_gen_set_template },
1323     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1324     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1325       (void (*)(void))ec_gen_settable_params },
1326     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
1327     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1328     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1329     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
1330     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
1331     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1332     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
1333     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1334     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1335     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
1336     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
1337     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1338     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1339     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1340     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1341       (void (*)(void))sm2_query_operation_name },
1342     { 0, NULL }
1343 };
1344 # endif
1345 #endif