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