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