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