1 /*
2 * Copyright 2020-2025 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 <string.h>
17 #include <openssl/core_dispatch.h>
18 #include <openssl/core_names.h>
19 #include <openssl/bn.h>
20 #include <openssl/err.h>
21 #include <openssl/objects.h>
22 #include <openssl/proverr.h>
23 #include <openssl/self_test.h>
24 #include "crypto/bn.h"
25 #include "crypto/ec.h"
26 #include "prov/implementations.h"
27 #include "prov/providercommon.h"
28 #include "prov/provider_ctx.h"
29 #include "prov/securitycheck.h"
30 #include "internal/fips.h"
31 #include "internal/param_build_set.h"
32
33 #ifndef FIPS_MODULE
34 # ifndef OPENSSL_NO_SM2
35 # include "crypto/sm2.h"
36 # endif
37 #endif
38
39 static OSSL_FUNC_keymgmt_new_fn ec_newdata;
40 static OSSL_FUNC_keymgmt_gen_init_fn ec_gen_init;
41 static OSSL_FUNC_keymgmt_gen_set_template_fn ec_gen_set_template;
42 static OSSL_FUNC_keymgmt_gen_set_params_fn ec_gen_set_params;
43 static OSSL_FUNC_keymgmt_gen_settable_params_fn ec_gen_settable_params;
44 static OSSL_FUNC_keymgmt_gen_get_params_fn ec_gen_get_params;
45 static OSSL_FUNC_keymgmt_gen_gettable_params_fn ec_gen_gettable_params;
46 static OSSL_FUNC_keymgmt_gen_fn ec_gen;
47 static OSSL_FUNC_keymgmt_gen_cleanup_fn ec_gen_cleanup;
48 static OSSL_FUNC_keymgmt_load_fn ec_load;
49 static OSSL_FUNC_keymgmt_free_fn ec_freedata;
50 static OSSL_FUNC_keymgmt_get_params_fn ec_get_params;
51 static OSSL_FUNC_keymgmt_gettable_params_fn ec_gettable_params;
52 static OSSL_FUNC_keymgmt_set_params_fn ec_set_params;
53 static OSSL_FUNC_keymgmt_settable_params_fn ec_settable_params;
54 static OSSL_FUNC_keymgmt_has_fn ec_has;
55 static OSSL_FUNC_keymgmt_match_fn ec_match;
56 static OSSL_FUNC_keymgmt_validate_fn ec_validate;
57 static OSSL_FUNC_keymgmt_import_fn ec_import;
58 static OSSL_FUNC_keymgmt_import_types_fn ec_import_types;
59 static OSSL_FUNC_keymgmt_export_fn ec_export;
60 static OSSL_FUNC_keymgmt_export_types_fn ec_export_types;
61 static OSSL_FUNC_keymgmt_query_operation_name_fn ec_query_operation_name;
62 static OSSL_FUNC_keymgmt_dup_fn ec_dup;
63 #ifndef FIPS_MODULE
64 # ifndef OPENSSL_NO_SM2
65 static OSSL_FUNC_keymgmt_new_fn sm2_newdata;
66 static OSSL_FUNC_keymgmt_gen_init_fn sm2_gen_init;
67 static OSSL_FUNC_keymgmt_gen_fn sm2_gen;
68 static OSSL_FUNC_keymgmt_get_params_fn sm2_get_params;
69 static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
70 static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
71 static OSSL_FUNC_keymgmt_import_fn sm2_import;
72 static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
73 static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
74 # endif
75 #endif
76
77 #define EC_DEFAULT_MD "SHA256"
78 #define EC_POSSIBLE_SELECTIONS \
79 (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)
80 #define SM2_DEFAULT_MD "SM3"
81
82 static
ec_query_operation_name(int operation_id)83 const char *ec_query_operation_name(int operation_id)
84 {
85 switch (operation_id) {
86 case OSSL_OP_KEYEXCH:
87 return "ECDH";
88 case OSSL_OP_SIGNATURE:
89 return "ECDSA";
90 }
91 return NULL;
92 }
93
94 #ifndef FIPS_MODULE
95 # ifndef OPENSSL_NO_SM2
96 static
sm2_query_operation_name(int operation_id)97 const char *sm2_query_operation_name(int operation_id)
98 {
99 switch (operation_id) {
100 case OSSL_OP_SIGNATURE:
101 return "SM2";
102 }
103 return NULL;
104 }
105 # endif
106 #endif
107
108 /*
109 * Callers of key_to_params MUST make sure that domparams_to_params is also
110 * called!
111 *
112 * This function only exports the bare keypair, domain parameters and other
113 * parameters are exported separately.
114 */
115 static ossl_inline
key_to_params(const EC_KEY * eckey,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[],int include_private,unsigned char ** pub_key)116 int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl,
117 OSSL_PARAM params[], int include_private,
118 unsigned char **pub_key)
119 {
120 BIGNUM *x = NULL, *y = NULL;
121 const BIGNUM *priv_key = NULL;
122 const EC_POINT *pub_point = NULL;
123 const EC_GROUP *ecg = NULL;
124 size_t pub_key_len = 0;
125 int ret = 0;
126 BN_CTX *bnctx = NULL;
127
128 if (eckey == NULL
129 || (ecg = EC_KEY_get0_group(eckey)) == NULL)
130 return 0;
131
132 priv_key = EC_KEY_get0_private_key(eckey);
133 pub_point = EC_KEY_get0_public_key(eckey);
134
135 if (pub_point != NULL) {
136 OSSL_PARAM *p = NULL, *px = NULL, *py = NULL;
137 /*
138 * EC_POINT_point2buf() can generate random numbers in some
139 * implementations so we need to ensure we use the correct libctx.
140 */
141 bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey));
142 if (bnctx == NULL)
143 goto err;
144
145
146 /* If we are doing a get then check first before decoding the point */
147 if (tmpl == NULL) {
148 p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
149 px = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_X);
150 py = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_PUB_Y);
151 }
152
153 if (p != NULL || tmpl != NULL) {
154 /* convert pub_point to a octet string according to the SECG standard */
155 point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
156
157 if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
158 format,
159 pub_key, bnctx)) == 0
160 || !ossl_param_build_set_octet_string(tmpl, p,
161 OSSL_PKEY_PARAM_PUB_KEY,
162 *pub_key, pub_key_len))
163 goto err;
164 }
165 if (px != NULL || py != NULL) {
166 if (px != NULL) {
167 x = BN_CTX_get(bnctx);
168 if (x == NULL)
169 goto err;
170 }
171 if (py != NULL) {
172 y = BN_CTX_get(bnctx);
173 if (y == NULL)
174 goto err;
175 }
176
177 if (!EC_POINT_get_affine_coordinates(ecg, pub_point, x, y, bnctx))
178 goto err;
179 if (px != NULL
180 && !ossl_param_build_set_bn(tmpl, px,
181 OSSL_PKEY_PARAM_EC_PUB_X, x))
182 goto err;
183 if (py != NULL
184 && !ossl_param_build_set_bn(tmpl, py,
185 OSSL_PKEY_PARAM_EC_PUB_Y, y))
186 goto err;
187 }
188 }
189
190 if (priv_key != NULL && include_private) {
191 size_t sz;
192 int ecbits;
193
194 /*
195 * Key import/export should never leak the bit length of the secret
196 * scalar in the key.
197 *
198 * For this reason, on export we use padded BIGNUMs with fixed length.
199 *
200 * When importing we also should make sure that, even if short lived,
201 * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
202 * soon as possible, so that any processing of this BIGNUM might opt for
203 * constant time implementations in the backend.
204 *
205 * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
206 * to preallocate the BIGNUM internal buffer to a fixed public size big
207 * enough that operations performed during the processing never trigger
208 * a realloc which would leak the size of the scalar through memory
209 * accesses.
210 *
211 * Fixed Length
212 * ------------
213 *
214 * The order of the large prime subgroup of the curve is our choice for
215 * a fixed public size, as that is generally the upper bound for
216 * generating a private key in EC cryptosystems and should fit all valid
217 * secret scalars.
218 *
219 * For padding on export we just use the bit length of the order
220 * converted to bytes (rounding up).
221 *
222 * For preallocating the BIGNUM storage we look at the number of "words"
223 * required for the internal representation of the order, and we
224 * preallocate 2 extra "words" in case any of the subsequent processing
225 * might temporarily overflow the order length.
226 */
227 ecbits = EC_GROUP_order_bits(ecg);
228 if (ecbits <= 0)
229 goto err;
230 sz = (ecbits + 7) / 8;
231
232 if (!ossl_param_build_set_bn_pad(tmpl, params,
233 OSSL_PKEY_PARAM_PRIV_KEY,
234 priv_key, sz))
235 goto err;
236 }
237 ret = 1;
238 err:
239 BN_CTX_free(bnctx);
240 return ret;
241 }
242
243 static ossl_inline
otherparams_to_params(const EC_KEY * ec,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[])244 int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl,
245 OSSL_PARAM params[])
246 {
247 int ecdh_cofactor_mode = 0, group_check = 0;
248 const char *name = NULL;
249 point_conversion_form_t format;
250
251 if (ec == NULL)
252 return 0;
253
254 format = EC_KEY_get_conv_form(ec);
255 name = ossl_ec_pt_format_id2name((int)format);
256 if (name != NULL
257 && !ossl_param_build_set_utf8_string(tmpl, params,
258 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
259 name))
260 return 0;
261
262 group_check = EC_KEY_get_flags(ec) & EC_FLAG_CHECK_NAMED_GROUP_MASK;
263 name = ossl_ec_check_group_type_id2name(group_check);
264 if (name != NULL
265 && !ossl_param_build_set_utf8_string(tmpl, params,
266 OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
267 name))
268 return 0;
269
270 if ((EC_KEY_get_enc_flags(ec) & EC_PKEY_NO_PUBKEY) != 0
271 && !ossl_param_build_set_int(tmpl, params,
272 OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, 0))
273 return 0;
274
275 ecdh_cofactor_mode =
276 (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
277 return ossl_param_build_set_int(tmpl, params,
278 OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
279 ecdh_cofactor_mode);
280 }
281
282 static
ec_newdata(void * provctx)283 void *ec_newdata(void *provctx)
284 {
285 if (!ossl_prov_is_running())
286 return NULL;
287 return EC_KEY_new_ex(PROV_LIBCTX_OF(provctx), NULL);
288 }
289
290 #ifndef FIPS_MODULE
291 # ifndef OPENSSL_NO_SM2
292 static
sm2_newdata(void * provctx)293 void *sm2_newdata(void *provctx)
294 {
295 if (!ossl_prov_is_running())
296 return NULL;
297 return EC_KEY_new_by_curve_name_ex(PROV_LIBCTX_OF(provctx), NULL, NID_sm2);
298 }
299 # endif
300 #endif
301
302 static
ec_freedata(void * keydata)303 void ec_freedata(void *keydata)
304 {
305 EC_KEY_free(keydata);
306 }
307
308 static
ec_has(const void * keydata,int selection)309 int ec_has(const void *keydata, int selection)
310 {
311 const EC_KEY *ec = keydata;
312 int ok = 1;
313
314 if (!ossl_prov_is_running() || ec == NULL)
315 return 0;
316 if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
317 return 1; /* the selection is not missing */
318
319 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
320 ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
321 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
322 ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
323 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
324 ok = ok && (EC_KEY_get0_group(ec) != NULL);
325 /*
326 * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be
327 * available, so no extra check is needed other than the previous one
328 * against EC_POSSIBLE_SELECTIONS.
329 */
330 return ok;
331 }
332
ec_match(const void * keydata1,const void * keydata2,int selection)333 static int ec_match(const void *keydata1, const void *keydata2, int selection)
334 {
335 const EC_KEY *ec1 = keydata1;
336 const EC_KEY *ec2 = keydata2;
337 const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
338 const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
339 BN_CTX *ctx = NULL;
340 int ok = 1;
341
342 if (!ossl_prov_is_running())
343 return 0;
344
345 ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec1));
346 if (ctx == NULL)
347 return 0;
348
349 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
350 ok = ok && group_a != NULL && group_b != NULL
351 && EC_GROUP_cmp(group_a, group_b, ctx) == 0;
352 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
353 int key_checked = 0;
354
355 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
356 const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
357 const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
358
359 if (pa != NULL && pb != NULL) {
360 ok = ok && EC_POINT_cmp(group_b, pa, pb, ctx) == 0;
361 key_checked = 1;
362 }
363 }
364 if (!key_checked
365 && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
366 const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
367 const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
368
369 if (pa != NULL && pb != NULL) {
370 ok = ok && BN_cmp(pa, pb) == 0;
371 key_checked = 1;
372 }
373 }
374 ok = ok && key_checked;
375 }
376 BN_CTX_free(ctx);
377 return ok;
378 }
379
common_check_sm2(const EC_KEY * ec,int sm2_wanted)380 static int common_check_sm2(const EC_KEY *ec, int sm2_wanted)
381 {
382 const EC_GROUP *ecg = NULL;
383
384 /*
385 * sm2_wanted: import the keys or domparams only on SM2 Curve
386 * !sm2_wanted: import the keys or domparams only not on SM2 Curve
387 */
388 if ((ecg = EC_KEY_get0_group(ec)) == NULL
389 || (sm2_wanted ^ (EC_GROUP_get_curve_name(ecg) == NID_sm2)))
390 return 0;
391 return 1;
392 }
393
394 static
common_import(void * keydata,int selection,const OSSL_PARAM params[],int sm2_wanted)395 int common_import(void *keydata, int selection, const OSSL_PARAM params[],
396 int sm2_wanted)
397 {
398 EC_KEY *ec = keydata;
399 int ok = 1;
400
401 if (!ossl_prov_is_running() || ec == NULL)
402 return 0;
403
404 /*
405 * In this implementation, we can export/import only keydata in the
406 * following combinations:
407 * - domain parameters (+optional other params)
408 * - public key with associated domain parameters (+optional other params)
409 * - private key with associated domain parameters and optional public key
410 * (+optional other params)
411 *
412 * This means:
413 * - domain parameters must always be requested
414 * - private key must be requested alongside public key
415 * - other parameters are always optional
416 */
417 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
418 return 0;
419
420 ok = ok && ossl_ec_group_fromdata(ec, params);
421
422 if (!common_check_sm2(ec, sm2_wanted))
423 return 0;
424
425 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
426 int include_private =
427 selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
428
429 ok = ok && ossl_ec_key_fromdata(ec, params, include_private);
430 }
431 if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
432 ok = ok && ossl_ec_key_otherparams_fromdata(ec, params);
433
434 return ok;
435 }
436
437 static
ec_import(void * keydata,int selection,const OSSL_PARAM params[])438 int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
439 {
440 return common_import(keydata, selection, params, 0);
441 }
442
443 #ifndef FIPS_MODULE
444 # ifndef OPENSSL_NO_SM2
445 static
sm2_import(void * keydata,int selection,const OSSL_PARAM params[])446 int sm2_import(void *keydata, int selection, const OSSL_PARAM params[])
447 {
448 return common_import(keydata, selection, params, 1);
449 }
450 # endif
451 #endif
452
453 static
ec_export(void * keydata,int selection,OSSL_CALLBACK * param_cb,void * cbarg)454 int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
455 void *cbarg)
456 {
457 EC_KEY *ec = keydata;
458 OSSL_PARAM_BLD *tmpl = NULL;
459 OSSL_PARAM *params = NULL;
460 unsigned char *pub_key = NULL, *genbuf = NULL;
461 BN_CTX *bnctx = NULL;
462 int ok = 1;
463
464 if (!ossl_prov_is_running() || ec == NULL)
465 return 0;
466
467 /*
468 * In this implementation, we can export/import only keydata in the
469 * following combinations:
470 * - domain parameters (+optional other params)
471 * - public key with associated domain parameters (+optional other params)
472 * - private key with associated public key and domain parameters
473 * (+optional other params)
474 *
475 * This means:
476 * - domain parameters must always be requested
477 * - private key must be requested alongside public key
478 * - other parameters are always optional
479 */
480 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
481 return 0;
482 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
483 && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
484 return 0;
485
486 tmpl = OSSL_PARAM_BLD_new();
487 if (tmpl == NULL)
488 return 0;
489
490 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
491 bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
492 if (bnctx == NULL) {
493 ok = 0;
494 goto end;
495 }
496 BN_CTX_start(bnctx);
497 ok = ok && ossl_ec_group_todata(EC_KEY_get0_group(ec), tmpl, NULL,
498 ossl_ec_key_get_libctx(ec),
499 ossl_ec_key_get0_propq(ec),
500 bnctx, &genbuf);
501 }
502
503 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
504 int include_private =
505 selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
506
507 ok = ok && key_to_params(ec, tmpl, NULL, include_private, &pub_key);
508 }
509 if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
510 ok = ok && otherparams_to_params(ec, tmpl, NULL);
511
512 if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
513 ok = 0;
514 goto end;
515 }
516
517 ok = param_cb(params, cbarg);
518 OSSL_PARAM_free(params);
519 end:
520 OSSL_PARAM_BLD_free(tmpl);
521 OPENSSL_free(pub_key);
522 OPENSSL_free(genbuf);
523 BN_CTX_end(bnctx);
524 BN_CTX_free(bnctx);
525 return ok;
526 }
527
528 /* IMEXPORT = IMPORT + EXPORT */
529
530 # define EC_IMEXPORTABLE_DOM_PARAMETERS \
531 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), \
532 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), \
533 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),\
534 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0), \
535 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0), \
536 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0), \
537 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0), \
538 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), \
539 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), \
540 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), \
541 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), \
542 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL)
543
544 # define EC_IMEXPORTABLE_PUBLIC_KEY \
545 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
546 # define EC_IMEXPORTABLE_PRIVATE_KEY \
547 OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
548 # define EC_IMEXPORTABLE_OTHER_PARAMETERS \
549 OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), \
550 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL)
551
552 /*
553 * Include all the possible combinations of OSSL_PARAM arrays for
554 * ec_imexport_types().
555 *
556 * They are in a separate file as it is ~100 lines of unreadable and
557 * uninteresting machine generated stuff.
558 */
559 #include "ec_kmgmt_imexport.inc"
560
561 static ossl_inline
ec_imexport_types(int selection)562 const OSSL_PARAM *ec_imexport_types(int selection)
563 {
564 int type_select = 0;
565
566 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
567 type_select += 1;
568 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
569 type_select += 2;
570 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
571 type_select += 4;
572 if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
573 type_select += 8;
574 return ec_types[type_select];
575 }
576
577 static
ec_import_types(int selection)578 const OSSL_PARAM *ec_import_types(int selection)
579 {
580 return ec_imexport_types(selection);
581 }
582
583 static
ec_export_types(int selection)584 const OSSL_PARAM *ec_export_types(int selection)
585 {
586 return ec_imexport_types(selection);
587 }
588
ec_get_ecm_params(const EC_GROUP * group,OSSL_PARAM params[])589 static int ec_get_ecm_params(const EC_GROUP *group, OSSL_PARAM params[])
590 {
591 #ifdef OPENSSL_NO_EC2M
592 return 1;
593 #else
594 int ret = 0, m;
595 unsigned int k1 = 0, k2 = 0, k3 = 0;
596 int basis_nid;
597 const char *basis_name = NULL;
598 int fid = EC_GROUP_get_field_type(group);
599
600 if (fid != NID_X9_62_characteristic_two_field)
601 return 1;
602
603 basis_nid = EC_GROUP_get_basis_type(group);
604 if (basis_nid == NID_X9_62_tpBasis)
605 basis_name = SN_X9_62_tpBasis;
606 else if (basis_nid == NID_X9_62_ppBasis)
607 basis_name = SN_X9_62_ppBasis;
608 else
609 goto err;
610
611 m = EC_GROUP_get_degree(group);
612 if (!ossl_param_build_set_int(NULL, params, OSSL_PKEY_PARAM_EC_CHAR2_M, m)
613 || !ossl_param_build_set_utf8_string(NULL, params,
614 OSSL_PKEY_PARAM_EC_CHAR2_TYPE,
615 basis_name))
616 goto err;
617
618 if (basis_nid == NID_X9_62_tpBasis) {
619 if (!EC_GROUP_get_trinomial_basis(group, &k1)
620 || !ossl_param_build_set_int(NULL, params,
621 OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS,
622 (int)k1))
623 goto err;
624 } else {
625 if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)
626 || !ossl_param_build_set_int(NULL, params,
627 OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, (int)k1)
628 || !ossl_param_build_set_int(NULL, params,
629 OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, (int)k2)
630 || !ossl_param_build_set_int(NULL, params,
631 OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, (int)k3))
632 goto err;
633 }
634 ret = 1;
635 err:
636 return ret;
637 #endif /* OPENSSL_NO_EC2M */
638 }
639
640 static
common_get_params(void * key,OSSL_PARAM params[],int sm2)641 int common_get_params(void *key, OSSL_PARAM params[], int sm2)
642 {
643 int ret = 0;
644 EC_KEY *eck = key;
645 const EC_GROUP *ecg = NULL;
646 OSSL_PARAM *p;
647 unsigned char *pub_key = NULL, *genbuf = NULL;
648 OSSL_LIB_CTX *libctx;
649 const char *propq;
650 BN_CTX *bnctx = NULL;
651
652 ecg = EC_KEY_get0_group(eck);
653 if (ecg == NULL) {
654 ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
655 return 0;
656 }
657
658 libctx = ossl_ec_key_get_libctx(eck);
659 propq = ossl_ec_key_get0_propq(eck);
660
661 bnctx = BN_CTX_new_ex(libctx);
662 if (bnctx == NULL)
663 return 0;
664 BN_CTX_start(bnctx);
665
666 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
667 && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
668 goto err;
669 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
670 && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
671 goto err;
672 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
673 int ecbits, sec_bits;
674
675 ecbits = EC_GROUP_order_bits(ecg);
676
677 /*
678 * The following estimates are based on the values published
679 * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
680 * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
681 *
682 * Note that the above reference explicitly categorizes algorithms in a
683 * discrete set of values {80, 112, 128, 192, 256}, and that it is
684 * relevant only for NIST approved Elliptic Curves, while OpenSSL
685 * applies the same logic also to other curves.
686 *
687 * Classifications produced by other standardazing bodies might differ,
688 * so the results provided for "bits of security" by this provider are
689 * to be considered merely indicative, and it is the users'
690 * responsibility to compare these values against the normative
691 * references that may be relevant for their intent and purposes.
692 */
693 if (ecbits >= 512)
694 sec_bits = 256;
695 else if (ecbits >= 384)
696 sec_bits = 192;
697 else if (ecbits >= 256)
698 sec_bits = 128;
699 else if (ecbits >= 224)
700 sec_bits = 112;
701 else if (ecbits >= 160)
702 sec_bits = 80;
703 else
704 sec_bits = ecbits / 2;
705
706 if (!OSSL_PARAM_set_int(p, sec_bits))
707 goto err;
708 }
709
710 if ((p = OSSL_PARAM_locate(params,
711 OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS))
712 != NULL) {
713 int explicitparams = EC_KEY_decoded_from_explicit_params(eck);
714
715 if (explicitparams < 0
716 || !OSSL_PARAM_set_int(p, explicitparams))
717 goto err;
718 }
719
720 if (!sm2) {
721 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
722 && !OSSL_PARAM_set_utf8_string(p, EC_DEFAULT_MD))
723 goto err;
724 } else {
725 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
726 && !OSSL_PARAM_set_utf8_string(p, SM2_DEFAULT_MD))
727 goto err;
728 }
729
730 /* SM2 doesn't support this PARAM */
731 if (!sm2) {
732 p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
733 if (p != NULL) {
734 int ecdh_cofactor_mode = 0;
735
736 ecdh_cofactor_mode =
737 (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
738
739 if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
740 goto err;
741 }
742 }
743 if ((p = OSSL_PARAM_locate(params,
744 OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
745 const EC_POINT *ecp = EC_KEY_get0_public_key(key);
746
747 if (ecp == NULL) {
748 ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
749 goto err;
750 }
751 p->return_size = EC_POINT_point2oct(ecg, ecp,
752 POINT_CONVERSION_UNCOMPRESSED,
753 p->data, p->data_size, bnctx);
754 if (p->return_size == 0)
755 goto err;
756 }
757
758 ret = ec_get_ecm_params(ecg, params)
759 && ossl_ec_group_todata(ecg, NULL, params, libctx, propq, bnctx,
760 &genbuf)
761 && key_to_params(eck, NULL, params, 1, &pub_key)
762 && otherparams_to_params(eck, NULL, params);
763 err:
764 OPENSSL_free(genbuf);
765 OPENSSL_free(pub_key);
766 BN_CTX_end(bnctx);
767 BN_CTX_free(bnctx);
768 return ret;
769 }
770
771 static
ec_get_params(void * key,OSSL_PARAM params[])772 int ec_get_params(void *key, OSSL_PARAM params[])
773 {
774 return common_get_params(key, params, 0);
775 }
776
777 #ifndef OPENSSL_NO_EC2M
778 # define EC2M_GETTABLE_DOM_PARAMS \
779 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_M, NULL), \
780 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_CHAR2_TYPE, NULL, 0), \
781 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_TP_BASIS, NULL), \
782 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K1, NULL), \
783 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K2, NULL), \
784 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_CHAR2_PP_K3, NULL),
785 #else
786 # define EC2M_GETTABLE_DOM_PARAMS
787 #endif
788
789 static const OSSL_PARAM ec_known_gettable_params[] = {
790 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
791 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
792 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
793 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
794 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
795 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
796 EC_IMEXPORTABLE_DOM_PARAMETERS,
797 EC2M_GETTABLE_DOM_PARAMS
798 EC_IMEXPORTABLE_PUBLIC_KEY,
799 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
800 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
801 EC_IMEXPORTABLE_PRIVATE_KEY,
802 EC_IMEXPORTABLE_OTHER_PARAMETERS,
803 OSSL_PARAM_END
804 };
805
806 static
ec_gettable_params(void * provctx)807 const OSSL_PARAM *ec_gettable_params(void *provctx)
808 {
809 return ec_known_gettable_params;
810 }
811
812 static const OSSL_PARAM ec_known_settable_params[] = {
813 OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
814 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
815 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
816 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
817 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
818 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC, NULL),
819 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, NULL, 0),
820 OSSL_PARAM_END
821 };
822
823 static
ec_settable_params(void * provctx)824 const OSSL_PARAM *ec_settable_params(void *provctx)
825 {
826 return ec_known_settable_params;
827 }
828
829 static
ec_set_params(void * key,const OSSL_PARAM params[])830 int ec_set_params(void *key, const OSSL_PARAM params[])
831 {
832 EC_KEY *eck = key;
833 const OSSL_PARAM *p;
834
835 if (key == NULL)
836 return 0;
837 if (ossl_param_is_empty(params))
838 return 1;
839
840 if (!ossl_ec_group_set_params((EC_GROUP *)EC_KEY_get0_group(key), params))
841 return 0;
842
843 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
844 if (p != NULL) {
845 BN_CTX *ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
846 int ret = 1;
847
848 if (ctx == NULL
849 || p->data_type != OSSL_PARAM_OCTET_STRING
850 || !EC_KEY_oct2key(key, p->data, p->data_size, ctx))
851 ret = 0;
852 BN_CTX_free(ctx);
853 if (!ret)
854 return 0;
855 }
856
857 return ossl_ec_key_otherparams_fromdata(eck, params);
858 }
859
860 #ifndef FIPS_MODULE
861 # ifndef OPENSSL_NO_SM2
862 static
sm2_get_params(void * key,OSSL_PARAM params[])863 int sm2_get_params(void *key, OSSL_PARAM params[])
864 {
865 return common_get_params(key, params, 1);
866 }
867
868 static const OSSL_PARAM sm2_known_gettable_params[] = {
869 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
870 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
871 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
872 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
873 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
874 OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, NULL),
875 EC_IMEXPORTABLE_DOM_PARAMETERS,
876 EC_IMEXPORTABLE_PUBLIC_KEY,
877 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
878 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
879 EC_IMEXPORTABLE_PRIVATE_KEY,
880 OSSL_PARAM_END
881 };
882
883 static
sm2_gettable_params(ossl_unused void * provctx)884 const OSSL_PARAM *sm2_gettable_params(ossl_unused void *provctx)
885 {
886 return sm2_known_gettable_params;
887 }
888
889 static const OSSL_PARAM sm2_known_settable_params[] = {
890 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
891 OSSL_PARAM_END
892 };
893
894 static
sm2_settable_params(ossl_unused void * provctx)895 const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx)
896 {
897 return sm2_known_settable_params;
898 }
899
900 static
sm2_validate(const void * keydata,int selection,int checktype)901 int sm2_validate(const void *keydata, int selection, int checktype)
902 {
903 const EC_KEY *eck = keydata;
904 int ok = 1;
905 BN_CTX *ctx = NULL;
906
907 if (!ossl_prov_is_running())
908 return 0;
909
910 if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
911 return 1; /* nothing to validate */
912
913 ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
914 if (ctx == NULL)
915 return 0;
916
917 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
918 ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
919
920 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
921 if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
922 ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
923 else
924 ok = ok && ossl_ec_key_public_check(eck, ctx);
925 }
926
927 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
928 ok = ok && ossl_sm2_key_private_check(eck);
929
930 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
931 ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
932
933 BN_CTX_free(ctx);
934 return ok;
935 }
936 # endif
937 #endif
938
939 static
ec_validate(const void * keydata,int selection,int checktype)940 int ec_validate(const void *keydata, int selection, int checktype)
941 {
942 const EC_KEY *eck = keydata;
943 int ok = 1;
944 BN_CTX *ctx = NULL;
945
946 if (!ossl_prov_is_running())
947 return 0;
948
949 if ((selection & EC_POSSIBLE_SELECTIONS) == 0)
950 return 1; /* nothing to validate */
951
952 ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eck));
953 if (ctx == NULL)
954 return 0;
955
956 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
957 int flags = EC_KEY_get_flags(eck);
958
959 if ((flags & EC_FLAG_CHECK_NAMED_GROUP) != 0)
960 ok = ok && EC_GROUP_check_named_curve(EC_KEY_get0_group(eck),
961 (flags & EC_FLAG_CHECK_NAMED_GROUP_NIST) != 0, ctx) > 0;
962 else
963 ok = ok && EC_GROUP_check(EC_KEY_get0_group(eck), ctx);
964 }
965
966 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
967 if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
968 ok = ok && ossl_ec_key_public_check_quick(eck, ctx);
969 else
970 ok = ok && ossl_ec_key_public_check(eck, ctx);
971 }
972
973 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
974 ok = ok && ossl_ec_key_private_check(eck);
975
976 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
977 ok = ok && ossl_ec_key_pairwise_check(eck, ctx);
978
979 BN_CTX_free(ctx);
980 return ok;
981 }
982
983 struct ec_gen_ctx {
984 OSSL_LIB_CTX *libctx;
985 char *group_name;
986 char *encoding;
987 char *pt_format;
988 char *group_check;
989 char *field_type;
990 BIGNUM *p, *a, *b, *order, *cofactor;
991 unsigned char *gen, *seed;
992 size_t gen_len, seed_len;
993 int selection;
994 int ecdh_mode;
995 EC_GROUP *gen_group;
996 unsigned char *dhkem_ikm;
997 size_t dhkem_ikmlen;
998 OSSL_FIPS_IND_DECLARE
999 };
1000
ec_gen_init(void * provctx,int selection,const OSSL_PARAM params[])1001 static void *ec_gen_init(void *provctx, int selection,
1002 const OSSL_PARAM params[])
1003 {
1004 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
1005 struct ec_gen_ctx *gctx = NULL;
1006
1007 if (!ossl_prov_is_running() || (selection & (EC_POSSIBLE_SELECTIONS)) == 0)
1008 return NULL;
1009
1010 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
1011 gctx->libctx = libctx;
1012 gctx->selection = selection;
1013 gctx->ecdh_mode = 0;
1014 OSSL_FIPS_IND_INIT(gctx)
1015 if (!ec_gen_set_params(gctx, params)) {
1016 OPENSSL_free(gctx);
1017 gctx = NULL;
1018 }
1019 }
1020 return gctx;
1021 }
1022
1023 #ifndef FIPS_MODULE
1024 # ifndef OPENSSL_NO_SM2
sm2_gen_init(void * provctx,int selection,const OSSL_PARAM params[])1025 static void *sm2_gen_init(void *provctx, int selection,
1026 const OSSL_PARAM params[])
1027 {
1028 struct ec_gen_ctx *gctx = ec_gen_init(provctx, selection, params);
1029
1030 if (gctx != NULL) {
1031 if (gctx->group_name != NULL)
1032 return gctx;
1033 if ((gctx->group_name = OPENSSL_strdup("sm2")) != NULL)
1034 return gctx;
1035 ec_gen_cleanup(gctx);
1036 }
1037 return NULL;
1038 }
1039 # endif
1040 #endif
1041
ec_gen_set_group(void * genctx,const EC_GROUP * src)1042 static int ec_gen_set_group(void *genctx, const EC_GROUP *src)
1043 {
1044 struct ec_gen_ctx *gctx = genctx;
1045 EC_GROUP *group;
1046
1047 group = EC_GROUP_dup(src);
1048 if (group == NULL) {
1049 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
1050 return 0;
1051 }
1052 EC_GROUP_free(gctx->gen_group);
1053 gctx->gen_group = group;
1054 return 1;
1055 }
1056
ec_gen_set_template(void * genctx,void * templ)1057 static int ec_gen_set_template(void *genctx, void *templ)
1058 {
1059 struct ec_gen_ctx *gctx = genctx;
1060 EC_KEY *ec = templ;
1061 const EC_GROUP *ec_group;
1062
1063 if (!ossl_prov_is_running() || gctx == NULL || ec == NULL)
1064 return 0;
1065 if ((ec_group = EC_KEY_get0_group(ec)) == NULL)
1066 return 0;
1067 return ec_gen_set_group(gctx, ec_group);
1068 }
1069
1070 #define COPY_INT_PARAM(params, key, val) \
1071 p = OSSL_PARAM_locate_const(params, key); \
1072 if (p != NULL && !OSSL_PARAM_get_int(p, &val)) \
1073 goto err;
1074
1075 #define COPY_UTF8_PARAM(params, key, val) \
1076 p = OSSL_PARAM_locate_const(params, key); \
1077 if (p != NULL) { \
1078 if (p->data_type != OSSL_PARAM_UTF8_STRING) \
1079 goto err; \
1080 OPENSSL_free(val); \
1081 val = OPENSSL_strdup(p->data); \
1082 if (val == NULL) \
1083 goto err; \
1084 }
1085
1086 #define COPY_OCTET_PARAM(params, key, val, len) \
1087 p = OSSL_PARAM_locate_const(params, key); \
1088 if (p != NULL) { \
1089 if (p->data_type != OSSL_PARAM_OCTET_STRING) \
1090 goto err; \
1091 OPENSSL_free(val); \
1092 len = p->data_size; \
1093 val = OPENSSL_memdup(p->data, p->data_size); \
1094 if (val == NULL) \
1095 goto err; \
1096 }
1097
1098 #define COPY_BN_PARAM(params, key, bn) \
1099 p = OSSL_PARAM_locate_const(params, key); \
1100 if (p != NULL) { \
1101 if (bn == NULL) \
1102 bn = BN_new(); \
1103 if (bn == NULL || !OSSL_PARAM_get_BN(p, &bn)) \
1104 goto err; \
1105 }
1106
ec_gen_set_params(void * genctx,const OSSL_PARAM params[])1107 static int ec_gen_set_params(void *genctx, const OSSL_PARAM params[])
1108 {
1109 int ret = 0;
1110 struct ec_gen_ctx *gctx = genctx;
1111 const OSSL_PARAM *p;
1112
1113 if (!OSSL_FIPS_IND_SET_CTX_PARAM(gctx, OSSL_FIPS_IND_SETTABLE0, params,
1114 OSSL_PKEY_PARAM_FIPS_KEY_CHECK))
1115 goto err;
1116
1117 COPY_INT_PARAM(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, gctx->ecdh_mode);
1118
1119 COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_GROUP_NAME, gctx->group_name);
1120 COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, gctx->field_type);
1121 COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_ENCODING, gctx->encoding);
1122 COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, gctx->pt_format);
1123 COPY_UTF8_PARAM(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, gctx->group_check);
1124
1125 COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_P, gctx->p);
1126 COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_A, gctx->a);
1127 COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_B, gctx->b);
1128 COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_ORDER, gctx->order);
1129 COPY_BN_PARAM(params, OSSL_PKEY_PARAM_EC_COFACTOR, gctx->cofactor);
1130
1131 COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_SEED, gctx->seed, gctx->seed_len);
1132 COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_EC_GENERATOR, gctx->gen,
1133 gctx->gen_len);
1134
1135 COPY_OCTET_PARAM(params, OSSL_PKEY_PARAM_DHKEM_IKM, gctx->dhkem_ikm,
1136 gctx->dhkem_ikmlen);
1137
1138 ret = 1;
1139 err:
1140 return ret;
1141 }
1142
ec_gen_set_group_from_params(struct ec_gen_ctx * gctx)1143 static int ec_gen_set_group_from_params(struct ec_gen_ctx *gctx)
1144 {
1145 int ret = 0;
1146 OSSL_PARAM_BLD *bld;
1147 OSSL_PARAM *params = NULL;
1148 EC_GROUP *group = NULL;
1149
1150 bld = OSSL_PARAM_BLD_new();
1151 if (bld == NULL)
1152 return 0;
1153
1154 if (gctx->encoding != NULL
1155 && !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_ENCODING,
1156 gctx->encoding, 0))
1157 goto err;
1158
1159 if (gctx->pt_format != NULL
1160 && !OSSL_PARAM_BLD_push_utf8_string(bld,
1161 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
1162 gctx->pt_format, 0))
1163 goto err;
1164
1165 if (gctx->group_name != NULL) {
1166 if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
1167 gctx->group_name, 0))
1168 goto err;
1169 /* Ignore any other parameters if there is a group name */
1170 goto build;
1171 } else if (gctx->field_type != NULL) {
1172 if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
1173 gctx->field_type, 0))
1174 goto err;
1175 } else {
1176 goto err;
1177 }
1178 if (gctx->p == NULL
1179 || gctx->a == NULL
1180 || gctx->b == NULL
1181 || gctx->order == NULL
1182 || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, gctx->p)
1183 || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, gctx->a)
1184 || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, gctx->b)
1185 || !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, gctx->order))
1186 goto err;
1187
1188 if (gctx->cofactor != NULL
1189 && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR,
1190 gctx->cofactor))
1191 goto err;
1192
1193 if (gctx->seed != NULL
1194 && !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED,
1195 gctx->seed, gctx->seed_len))
1196 goto err;
1197
1198 if (gctx->gen == NULL
1199 || !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR,
1200 gctx->gen, gctx->gen_len))
1201 goto err;
1202 build:
1203 params = OSSL_PARAM_BLD_to_param(bld);
1204 if (params == NULL)
1205 goto err;
1206 group = EC_GROUP_new_from_params(params, gctx->libctx, NULL);
1207 if (group == NULL)
1208 goto err;
1209
1210 EC_GROUP_free(gctx->gen_group);
1211 gctx->gen_group = group;
1212
1213 ret = 1;
1214 err:
1215 OSSL_PARAM_free(params);
1216 OSSL_PARAM_BLD_free(bld);
1217 return ret;
1218 }
1219
ec_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)1220 static const OSSL_PARAM *ec_gen_settable_params(ossl_unused void *genctx,
1221 ossl_unused void *provctx)
1222 {
1223 static OSSL_PARAM settable[] = {
1224 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
1225 OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
1226 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0),
1227 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL, 0),
1228 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0),
1229 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0),
1230 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0),
1231 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0),
1232 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0),
1233 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0),
1234 OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0),
1235 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0),
1236 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0),
1237 OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_PKEY_PARAM_FIPS_KEY_CHECK)
1238 OSSL_PARAM_END
1239 };
1240 return settable;
1241 }
1242
ec_gen_gettable_params(ossl_unused void * genctx,ossl_unused void * provctx)1243 static const OSSL_PARAM *ec_gen_gettable_params(ossl_unused void *genctx,
1244 ossl_unused void *provctx)
1245 {
1246 static const OSSL_PARAM known_ec_gen_gettable_ctx_params[] = {
1247 OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
1248 OSSL_PARAM_END
1249 };
1250 return known_ec_gen_gettable_ctx_params;
1251 }
1252
ec_gen_get_params(void * genctx,OSSL_PARAM * params)1253 static int ec_gen_get_params(void *genctx, OSSL_PARAM *params)
1254 {
1255 struct ec_gen_ctx *gctx = genctx;
1256
1257 if (gctx == NULL)
1258 return 0;
1259
1260 if (!OSSL_FIPS_IND_GET_CTX_PARAM(gctx, params))
1261 return 0;
1262
1263 return 1;
1264 }
1265
ec_gen_assign_group(EC_KEY * ec,EC_GROUP * group)1266 static int ec_gen_assign_group(EC_KEY *ec, EC_GROUP *group)
1267 {
1268 if (group == NULL) {
1269 ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET);
1270 return 0;
1271 }
1272 return EC_KEY_set_group(ec, group) > 0;
1273 }
1274
1275 /*
1276 * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1277 */
ec_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)1278 static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1279 {
1280 struct ec_gen_ctx *gctx = genctx;
1281 EC_KEY *ec = NULL;
1282 int ret = 0;
1283
1284 if (!ossl_prov_is_running()
1285 || gctx == NULL
1286 || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1287 return NULL;
1288
1289 if (gctx->gen_group == NULL) {
1290 if (!ec_gen_set_group_from_params(gctx))
1291 goto err;
1292 } else {
1293 if (gctx->encoding != NULL) {
1294 int flags = ossl_ec_encoding_name2id(gctx->encoding);
1295
1296 if (flags < 0)
1297 goto err;
1298 EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1299 }
1300 if (gctx->pt_format != NULL) {
1301 int format = ossl_ec_pt_format_name2id(gctx->pt_format);
1302
1303 if (format < 0)
1304 goto err;
1305 EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1306 }
1307 }
1308 #ifdef FIPS_MODULE
1309 if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(gctx),
1310 OSSL_FIPS_IND_SETTABLE0, gctx->libctx,
1311 gctx->gen_group, "EC KeyGen", 1))
1312 goto err;
1313 #endif
1314
1315 /* We must always assign a group, no matter what */
1316 ret = ec_gen_assign_group(ec, gctx->gen_group);
1317
1318 /* Whether you want it or not, you get a keypair, not just one half */
1319 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
1320 #ifndef FIPS_MODULE
1321 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0)
1322 ret = ret && ossl_ec_generate_key_dhkem(ec, gctx->dhkem_ikm,
1323 gctx->dhkem_ikmlen);
1324 else
1325 #endif
1326 ret = ret && EC_KEY_generate_key(ec);
1327 }
1328
1329 if (gctx->ecdh_mode != -1)
1330 ret = ret && ossl_ec_set_ecdh_cofactor_mode(ec, gctx->ecdh_mode);
1331
1332 if (gctx->group_check != NULL)
1333 ret = ret && ossl_ec_set_check_group_type_from_name(ec,
1334 gctx->group_check);
1335 #ifdef FIPS_MODULE
1336 if (ret > 0
1337 && !ossl_fips_self_testing()
1338 && EC_KEY_get0_public_key(ec) != NULL
1339 && EC_KEY_get0_private_key(ec) != NULL
1340 && EC_KEY_get0_group(ec) != NULL) {
1341 BN_CTX *bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
1342
1343 ret = bnctx != NULL && ossl_ec_key_pairwise_check(ec, bnctx);
1344 BN_CTX_free(bnctx);
1345 if (ret <= 0)
1346 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
1347 }
1348 #endif /* FIPS_MODULE */
1349
1350 if (ret)
1351 return ec;
1352 err:
1353 /* Something went wrong, throw the key away */
1354 EC_KEY_free(ec);
1355 return NULL;
1356 }
1357
1358 #ifndef FIPS_MODULE
1359 # ifndef OPENSSL_NO_SM2
1360 /*
1361 * The callback arguments (osslcb & cbarg) are not used by EC_KEY generation
1362 */
sm2_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)1363 static void *sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
1364 {
1365 struct ec_gen_ctx *gctx = genctx;
1366 EC_KEY *ec = NULL;
1367 int ret = 1;
1368
1369 if (gctx == NULL
1370 || (ec = EC_KEY_new_ex(gctx->libctx, NULL)) == NULL)
1371 return NULL;
1372
1373 if (gctx->gen_group == NULL) {
1374 if (!ec_gen_set_group_from_params(gctx))
1375 goto err;
1376 } else {
1377 if (gctx->encoding) {
1378 int flags = ossl_ec_encoding_name2id(gctx->encoding);
1379
1380 if (flags < 0)
1381 goto err;
1382 EC_GROUP_set_asn1_flag(gctx->gen_group, flags);
1383 }
1384 if (gctx->pt_format != NULL) {
1385 int format = ossl_ec_pt_format_name2id(gctx->pt_format);
1386
1387 if (format < 0)
1388 goto err;
1389 EC_GROUP_set_point_conversion_form(gctx->gen_group, format);
1390 }
1391 }
1392
1393 /* We must always assign a group, no matter what */
1394 ret = ec_gen_assign_group(ec, gctx->gen_group);
1395
1396 /* Whether you want it or not, you get a keypair, not just one half */
1397 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
1398 ret = ret && EC_KEY_generate_key(ec);
1399
1400 if (ret)
1401 return ec;
1402 err:
1403 /* Something went wrong, throw the key away */
1404 EC_KEY_free(ec);
1405 return NULL;
1406 }
1407 # endif
1408 #endif
1409
ec_gen_cleanup(void * genctx)1410 static void ec_gen_cleanup(void *genctx)
1411 {
1412 struct ec_gen_ctx *gctx = genctx;
1413
1414 if (gctx == NULL)
1415 return;
1416
1417 OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
1418 EC_GROUP_free(gctx->gen_group);
1419 BN_free(gctx->p);
1420 BN_free(gctx->a);
1421 BN_free(gctx->b);
1422 BN_free(gctx->order);
1423 BN_free(gctx->cofactor);
1424 OPENSSL_free(gctx->group_name);
1425 OPENSSL_free(gctx->field_type);
1426 OPENSSL_free(gctx->pt_format);
1427 OPENSSL_free(gctx->encoding);
1428 OPENSSL_free(gctx->seed);
1429 OPENSSL_free(gctx->gen);
1430 OPENSSL_free(gctx);
1431 }
1432
common_load(const void * reference,size_t reference_sz,int sm2_wanted)1433 static void *common_load(const void *reference, size_t reference_sz,
1434 int sm2_wanted)
1435 {
1436 EC_KEY *ec = NULL;
1437
1438 if (ossl_prov_is_running() && reference_sz == sizeof(ec)) {
1439 /* The contents of the reference is the address to our object */
1440 ec = *(EC_KEY **)reference;
1441
1442 if (!common_check_sm2(ec, sm2_wanted))
1443 return NULL;
1444
1445 /* We grabbed, so we detach it */
1446 *(EC_KEY **)reference = NULL;
1447 return ec;
1448 }
1449 return NULL;
1450 }
1451
ec_load(const void * reference,size_t reference_sz)1452 static void *ec_load(const void *reference, size_t reference_sz)
1453 {
1454 return common_load(reference, reference_sz, 0);
1455 }
1456
1457 #ifndef FIPS_MODULE
1458 # ifndef OPENSSL_NO_SM2
sm2_load(const void * reference,size_t reference_sz)1459 static void *sm2_load(const void *reference, size_t reference_sz)
1460 {
1461 return common_load(reference, reference_sz, 1);
1462 }
1463 # endif
1464 #endif
1465
ec_dup(const void * keydata_from,int selection)1466 static void *ec_dup(const void *keydata_from, int selection)
1467 {
1468 if (ossl_prov_is_running())
1469 return ossl_ec_key_dup(keydata_from, selection);
1470 return NULL;
1471 }
1472
1473 const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {
1474 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
1475 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))ec_gen_init },
1476 { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1477 (void (*)(void))ec_gen_set_template },
1478 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1479 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1480 (void (*)(void))ec_gen_settable_params },
1481 { OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS, (void (*)(void))ec_gen_get_params },
1482 { OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS,
1483 (void (*)(void))ec_gen_gettable_params },
1484 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))ec_gen },
1485 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1486 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ec_load },
1487 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1488 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
1489 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
1490 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1491 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
1492 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1493 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1494 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))ec_validate },
1495 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
1496 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1497 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1498 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1499 { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1500 (void (*)(void))ec_query_operation_name },
1501 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
1502 OSSL_DISPATCH_END
1503 };
1504
1505 #ifndef FIPS_MODULE
1506 # ifndef OPENSSL_NO_SM2
1507 const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
1508 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },
1509 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },
1510 { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
1511 (void (*)(void))ec_gen_set_template },
1512 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
1513 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
1514 (void (*)(void))ec_gen_settable_params },
1515 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
1516 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
1517 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },
1518 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
1519 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))sm2_get_params },
1520 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))sm2_gettable_params },
1521 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
1522 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))sm2_settable_params },
1523 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
1524 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
1525 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
1526 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
1527 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
1528 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
1529 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
1530 { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
1531 (void (*)(void))sm2_query_operation_name },
1532 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
1533 OSSL_DISPATCH_END
1534 };
1535 # endif
1536 #endif
1537