[PROV][KEYMGMT][EC] Import/export of priv_key as padded const time BN
[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 <openssl/core_numbers.h>
17 #include <openssl/core_names.h>
18 #include <openssl/bn.h>
19 #include <openssl/ec.h>
20 #include <openssl/objects.h>
21 #include <openssl/params.h>
22 #include "crypto/bn.h"
23 #include "internal/param_build.h"
24 #include "prov/implementations.h"
25 #include "prov/providercommon.h"
26
27 static OSSL_OP_keymgmt_new_fn ec_newdata;
28 static OSSL_OP_keymgmt_free_fn ec_freedata;
29 static OSSL_OP_keymgmt_get_params_fn ec_get_params;
30 static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params;
31 static OSSL_OP_keymgmt_set_params_fn ec_set_params;
32 static OSSL_OP_keymgmt_settable_params_fn ec_settable_params;
33 static OSSL_OP_keymgmt_has_fn ec_has;
34 static OSSL_OP_keymgmt_import_fn ec_import;
35 static OSSL_OP_keymgmt_import_types_fn ec_import_types;
36 static OSSL_OP_keymgmt_export_fn ec_export;
37 static OSSL_OP_keymgmt_export_types_fn ec_export_types;
38 static OSSL_OP_keymgmt_query_operation_name_fn ec_query_operation_name;
39
40 #define EC_POSSIBLE_SELECTIONS                 \
41     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
42
43 static
44 const char *ec_query_operation_name(int operation_id)
45 {
46     switch (operation_id) {
47     case OSSL_OP_KEYEXCH:
48         return "ECDH";
49 #if 0
50     case OSSL_OP_SIGNATURE:
51         return deflt_signature;
52 #endif
53     }
54     return NULL;
55 }
56
57 static ossl_inline
58 int params_to_domparams(EC_KEY *ec, const OSSL_PARAM params[])
59 {
60     const OSSL_PARAM *param_ec_name;
61     EC_GROUP *ecg = NULL;
62     char *curve_name = NULL;
63     int ok = 0;
64
65     if (ec == NULL)
66         return 0;
67
68     param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME);
69     if (param_ec_name == NULL) {
70         /* explicit parameters */
71
72         /*
73          * TODO(3.0): should we support explicit parameters curves?
74          */
75         return 0;
76     } else {
77         /* named curve */
78         int curve_nid;
79
80         if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0)
81                 || curve_name == NULL
82                 || (curve_nid = OBJ_sn2nid(curve_name)) == NID_undef)
83             goto err;
84
85         if ((ecg = EC_GROUP_new_by_curve_name(curve_nid)) == NULL)
86             goto err;
87     }
88
89     if (!EC_KEY_set_group(ec, ecg))
90         goto err;
91
92     /*
93      * TODO(3.0): if the group has changed, should we invalidate the private and
94      * public key?
95      */
96
97     ok = 1;
98
99  err:
100     OPENSSL_free(curve_name);
101     EC_GROUP_free(ecg);
102     return ok;
103 }
104
105 static ossl_inline
106 int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
107 {
108     const EC_GROUP *ecg;
109     int curve_nid;
110
111     if (ec == NULL)
112         return 0;
113
114     ecg = EC_KEY_get0_group(ec);
115     if (ecg == NULL)
116         return 0;
117
118     curve_nid = EC_GROUP_get_curve_name(ecg);
119
120     if (curve_nid == NID_undef) {
121         /* explicit parameters */
122
123         /*
124          * TODO(3.0): should we support explicit parameters curves?
125          */
126         return 0;
127     } else {
128         /* named curve */
129         const char *curve_name = NULL;
130
131         if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
132             return 0;
133
134         if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
135             return 0;
136     }
137
138     return 1;
139 }
140
141 /*
142  * Callers of params_to_key MUST make sure that params_to_domparams has been
143  * called before!
144  *
145  * This function only imports the bare keypair, domain parameters and other
146  * parameters are imported separately, and domain parameters are required to
147  * define a keypair.
148  */
149 static ossl_inline
150 int params_to_key(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
151 {
152     const OSSL_PARAM *param_priv_key, *param_pub_key;
153     BIGNUM *priv_key = NULL;
154     unsigned char *pub_key = NULL;
155     size_t pub_key_len;
156     const EC_GROUP *ecg = NULL;
157     EC_POINT *pub_point = NULL;
158     int ok = 0;
159
160     ecg = EC_KEY_get0_group(ec);
161     if (ecg == NULL)
162         return 0;
163
164     param_priv_key =
165         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
166     param_pub_key =
167         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
168
169     /*
170      * We want to have at least a public key either way, so we end up
171      * requiring it unconditionally.
172      */
173     if (param_pub_key == NULL
174             || !OSSL_PARAM_get_octet_string(param_pub_key,
175                                             (void **)&pub_key, 0, &pub_key_len)
176             || (pub_point = EC_POINT_new(ecg)) == NULL
177             || !EC_POINT_oct2point(ecg, pub_point,
178                                    pub_key, pub_key_len, NULL))
179         goto err;
180
181     if (param_priv_key != NULL && include_private) {
182         int fixed_top;
183         const BIGNUM *order;
184
185         /*
186          * Key import/export should never leak the bit length of the secret
187          * scalar in the key.
188          *
189          * For this reason, on export we use padded BIGNUMs with fixed length.
190          *
191          * When importing we also should make sure that, even if short lived,
192          * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
193          * soon as possible, so that any processing of this BIGNUM might opt for
194          * constant time implementations in the backend.
195          *
196          * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
197          * to preallocate the BIGNUM internal buffer to a fixed public size big
198          * enough that operations performed during the processing never trigger
199          * a realloc which would leak the size of the scalar through memory
200          * accesses.
201          *
202          * Fixed Length
203          * ------------
204          *
205          * The order of the large prime subgroup of the curve is our choice for
206          * a fixed public size, as that is generally the upper bound for
207          * generating a private key in EC cryptosystems and should fit all valid
208          * secret scalars.
209          *
210          * For padding on export we just use the bit length of the order
211          * converted to bytes (rounding up).
212          *
213          * For preallocating the BIGNUM storage we look at the number of "words"
214          * required for the internal representation of the order, and we
215          * preallocate 2 extra "words" in case any of the subsequent processing
216          * might temporarily overflow the order length.
217          */
218         order = EC_GROUP_get0_order(ecg);
219         if (order == NULL || BN_is_zero(order))
220             goto err;
221
222         fixed_top = bn_get_top(order) + 2;
223
224         if ((priv_key = BN_new()) == NULL)
225             goto err;
226         if (bn_wexpand(priv_key, fixed_top) == NULL)
227             goto err;
228         BN_set_flags(priv_key, BN_FLG_CONSTTIME);
229
230         if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
231             goto err;
232     }
233
234     if (priv_key != NULL
235             && !EC_KEY_set_private_key(ec, priv_key))
236         goto err;
237
238     if (!EC_KEY_set_public_key(ec, pub_point))
239         goto err;
240
241     ok = 1;
242
243  err:
244     BN_clear_free(priv_key);
245     OPENSSL_free(pub_key);
246     EC_POINT_free(pub_point);
247     return ok;
248 }
249
250 /*
251  * Callers of key_to_params MUST make sure that domparams_to_params is also
252  * called!
253  *
254  * This function only exports the bare keypair, domain parameters and other
255  * parameters are exported separately.
256  */
257 static ossl_inline
258 int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private)
259 {
260     const BIGNUM *priv_key = NULL;
261     const EC_POINT *pub_point = NULL;
262     const EC_GROUP *ecg = NULL;
263     unsigned char *pub_key = NULL;
264     size_t pub_key_len = 0;
265     int ret = 0;
266
267     if (eckey == NULL)
268         return 0;
269
270     ecg = EC_KEY_get0_group(eckey);
271     priv_key = EC_KEY_get0_private_key(eckey);
272     pub_point = EC_KEY_get0_public_key(eckey);
273
274     /* group and public_key must be present, priv_key is optional */
275     if (ecg == NULL || pub_point == NULL)
276         return 0;
277     if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
278                                           POINT_CONVERSION_COMPRESSED,
279                                           &pub_key, NULL)) == 0)
280         return 0;
281
282     if (!ossl_param_bld_push_octet_string(tmpl,
283                                           OSSL_PKEY_PARAM_PUB_KEY,
284                                           pub_key, pub_key_len))
285         goto err;
286
287     if (priv_key != NULL && include_private) {
288         size_t sz;
289         int ecbits;
290
291         /*
292          * Key import/export should never leak the bit length of the secret
293          * scalar in the key.
294          *
295          * For this reason, on export we use padded BIGNUMs with fixed length.
296          *
297          * When importing we also should make sure that, even if short lived,
298          * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
299          * soon as possible, so that any processing of this BIGNUM might opt for
300          * constant time implementations in the backend.
301          *
302          * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
303          * to preallocate the BIGNUM internal buffer to a fixed public size big
304          * enough that operations performed during the processing never trigger
305          * a realloc which would leak the size of the scalar through memory
306          * accesses.
307          *
308          * Fixed Length
309          * ------------
310          *
311          * The order of the large prime subgroup of the curve is our choice for
312          * a fixed public size, as that is generally the upper bound for
313          * generating a private key in EC cryptosystems and should fit all valid
314          * secret scalars.
315          *
316          * For padding on export we just use the bit length of the order
317          * converted to bytes (rounding up).
318          *
319          * For preallocating the BIGNUM storage we look at the number of "words"
320          * required for the internal representation of the order, and we
321          * preallocate 2 extra "words" in case any of the subsequent processing
322          * might temporarily overflow the order length.
323          */
324         ecbits = EC_GROUP_order_bits(ecg);
325         if (ecbits <= 0)
326             goto err;
327         sz = (ecbits + 7 ) / 8;
328         if (!ossl_param_bld_push_BN_pad(tmpl,
329                                         OSSL_PKEY_PARAM_PRIV_KEY,
330                                         priv_key, sz))
331             goto err;
332     }
333
334     ret = 1;
335
336  err:
337     OPENSSL_free(pub_key);
338     return ret;
339 }
340
341 static ossl_inline
342 int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p)
343 {
344     const EC_GROUP *ecg = EC_KEY_get0_group(ec);
345     const BIGNUM *cofactor;
346     int mode;
347
348     if (!OSSL_PARAM_get_int(p, &mode))
349         return 0;
350
351     /*
352      * mode can be only 0 for disable, or 1 for enable here.
353      *
354      * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
355      * also supports mode == -1 with the meaning of "reset to the default for
356      * the associated key".
357      */
358     if (mode < 0 || mode > 1)
359         return 0;
360
361     if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
362         return 0;
363
364     /* ECDH cofactor mode has no effect if cofactor is 1 */
365     if (BN_is_one(cofactor))
366         return 1;
367
368     if (mode == 1)
369         EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
370     else if (mode == 0)
371         EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
372
373     return 1;
374 }
375
376 static ossl_inline
377 int params_to_otherparams(EC_KEY *ec, const OSSL_PARAM params[])
378 {
379     const OSSL_PARAM *p;
380
381     if (ec == NULL)
382         return 0;
383
384     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
385     if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p))
386         return 0;
387
388     return 1;
389 }
390
391 static ossl_inline
392 int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
393 {
394     int ecdh_cofactor_mode = 0;
395
396     if (ec == NULL)
397         return 0;
398
399     ecdh_cofactor_mode =
400         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
401     if (!ossl_param_bld_push_int(tmpl,
402                 OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
403                 ecdh_cofactor_mode))
404         return 0;
405
406     return 1;
407 }
408
409 static
410 void *ec_newdata(void *provctx)
411 {
412     return EC_KEY_new();
413 }
414
415 static
416 void ec_freedata(void *keydata)
417 {
418     EC_KEY_free(keydata);
419 }
420
421 static
422 int ec_has(void *keydata, int selection)
423 {
424     EC_KEY *ec = keydata;
425     int ok = 0;
426
427     if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
428         ok = 1;
429
430     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
431         ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
432     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
433         ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
434     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
435         ok = ok && (EC_KEY_get0_group(ec) != NULL);
436     /*
437      * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be available,
438      * so no extra check is needed other than the previous one against
439      * EC_POSSIBLE_SELECTIONS.
440      */
441
442     return ok;
443 }
444
445 static
446 int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
447 {
448     EC_KEY *ec = keydata;
449     int ok = 0;
450
451     if (ec == NULL)
452         return 0;
453
454     /*
455      * In this implementation, we can export/import only keydata in the
456      * following combinations:
457      *   - domain parameters only
458      *   - public key with associated domain parameters (+optional other params)
459      *   - private key with associated public key and domain parameters
460      *         (+optional other params)
461      *
462      * This means:
463      *   - domain parameters must always be requested
464      *   - private key must be requested alongside public key
465      *   - other parameters must be requested only alongside a key
466      */
467     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
468         return 0;
469     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
470             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
471         return 0;
472     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
473             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
474         return 0;
475
476     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
477         ok = ok && params_to_domparams(ec, params);
478     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
479         int include_private =
480             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
481
482         ok = ok && params_to_key(ec, params, include_private);
483     }
484     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
485         ok = ok && params_to_otherparams(ec, params);
486
487     return ok;
488 }
489
490 static
491 int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
492               void *cbarg)
493 {
494     EC_KEY *ec = keydata;
495     OSSL_PARAM_BLD tmpl;
496     OSSL_PARAM *params = NULL;
497     int ok = 1;
498
499     if (ec == NULL)
500         return 0;
501
502     /*
503      * In this implementation, we can export/import only keydata in the
504      * following combinations:
505      *   - domain parameters only
506      *   - public key with associated domain parameters (+optional other params)
507      *   - private key with associated public key and domain parameters
508      *         (+optional other params)
509      *
510      * This means:
511      *   - domain parameters must always be requested
512      *   - private key must be requested alongside public key
513      *   - other parameters must be requested only alongside a key
514      */
515     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
516         return 0;
517     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
518             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
519         return 0;
520     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
521             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
522         return 0;
523
524     ossl_param_bld_init(&tmpl);
525
526     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
527         ok = ok && domparams_to_params(ec, &tmpl);
528     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
529         int include_private =
530             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
531
532         ok = ok && key_to_params(ec, &tmpl, include_private);
533     }
534     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
535         ok = ok && otherparams_to_params(ec, &tmpl);
536
537     if (!ok
538         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
539         return 0;
540
541     ok = param_cb(params, cbarg);
542     ossl_param_bld_free(params);
543     return ok;
544 }
545
546 /* IMEXPORT = IMPORT + EXPORT */
547
548 # define EC_IMEXPORTABLE_DOM_PARAMETERS                          \
549     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_NAME, NULL, 0)
550 # define EC_IMEXPORTABLE_PUBLIC_KEY                              \
551     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
552 # define EC_IMEXPORTABLE_PRIVATE_KEY                             \
553     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
554 # define EC_IMEXPORTABLE_OTHER_PARAMETERS                        \
555     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL)
556
557 /*
558  * Include all the possible combinations of OSSL_PARAM arrays for
559  * ec_imexport_types().
560  *
561  * They are in a separate file as it is ~100 lines of unreadable and
562  * uninteresting machine generated stuff.
563  *
564  * TODO(3.0): the generated list looks quite ugly, as to cover all possible
565  * combinations of the bits in `selection`, it also includes combinations that
566  * are not really useful: we might want to consider alternatives to this
567  * solution.
568  */
569 #include "ec_kmgmt_imexport.inc"
570
571 static ossl_inline
572 const OSSL_PARAM *ec_imexport_types(int selection)
573 {
574     int type_select = 0;
575
576     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
577         type_select += 1;
578     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
579         type_select += 2;
580     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
581         type_select += 4;
582     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
583         type_select += 8;
584     return ec_types[type_select];
585 }
586
587 static
588 const OSSL_PARAM *ec_import_types(int selection)
589 {
590     return ec_imexport_types(selection);
591 }
592
593 static
594 const OSSL_PARAM *ec_export_types(int selection)
595 {
596     return ec_imexport_types(selection);
597 }
598
599 static
600 int ec_get_params(void *key, OSSL_PARAM params[])
601 {
602     EC_KEY *eck = key;
603     const EC_GROUP *ecg = NULL;
604     OSSL_PARAM *p;
605
606     ecg = EC_KEY_get0_group(eck);
607     if (ecg == NULL)
608         return 0;
609
610     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
611         && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
612         return 0;
613     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
614         && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
615         return 0;
616     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
617         int ecbits, sec_bits;
618
619         ecbits = EC_GROUP_order_bits(ecg);
620
621         /*
622          * The following estimates are based on the values published
623          * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
624          * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
625          *
626          * Note that the above reference explicitly categorizes algorithms in a
627          * discrete set of values {80, 112, 128, 192, 256}, and that it is
628          * relevant only for NIST approved Elliptic Curves, while OpenSSL
629          * applies the same logic also to other curves.
630          *
631          * Classifications produced by other standardazing bodies might differ,
632          * so the results provided for "bits of security" by this provider are
633          * to be considered merely indicative, and it is the users'
634          * responsibility to compare these values against the normative
635          * references that may be relevant for their intent and purposes.
636          */
637         if (ecbits >= 512)
638             sec_bits = 256;
639         else if (ecbits >= 384)
640             sec_bits = 192;
641         else if (ecbits >= 256)
642             sec_bits = 128;
643         else if (ecbits >= 224)
644             sec_bits = 112;
645         else if (ecbits >= 160)
646             sec_bits = 80;
647         else
648             sec_bits = ecbits / 2;
649
650         if (!OSSL_PARAM_set_int(p, sec_bits))
651             return 0;
652     }
653
654     p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
655     if (p != NULL) {
656         int ecdh_cofactor_mode = 0;
657
658         ecdh_cofactor_mode =
659             (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
660
661         if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
662             return 0;
663     }
664
665     return 1;
666 }
667
668 static const OSSL_PARAM ec_known_gettable_params[] = {
669     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
670     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
671     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
672     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
673     OSSL_PARAM_END
674 };
675
676 static
677 const OSSL_PARAM *ec_gettable_params(void)
678 {
679     return ec_known_gettable_params;
680 }
681
682 static const OSSL_PARAM ec_known_settable_params[] = {
683     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
684     OSSL_PARAM_END
685 };
686
687 static
688 const OSSL_PARAM *ec_settable_params(void)
689 {
690     return ec_known_settable_params;
691 }
692
693 static
694 int ec_set_params(void *key, const OSSL_PARAM params[])
695 {
696     EC_KEY *eck = key;
697     const OSSL_PARAM *p;
698
699     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
700     if (p != NULL && !ec_set_param_ecdh_cofactor_mode(eck, p))
701         return 0;
702
703     return 1;
704 }
705
706 const OSSL_DISPATCH ec_keymgmt_functions[] = {
707     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
708     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
709     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
710     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
711     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
712     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
713     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
714     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
715     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
716     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
717     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
718     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
719         (void (*)(void))ec_query_operation_name },
720     { 0, NULL }
721 };