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