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 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 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 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 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 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 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 303 void ec_freedata(void *keydata) 304 { 305 EC_KEY_free(keydata); 306 } 307 308 static 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 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 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 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 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 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 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 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 578 const OSSL_PARAM *ec_import_types(int selection) 579 { 580 return ec_imexport_types(selection); 581 } 582 583 static 584 const OSSL_PARAM *ec_export_types(int selection) 585 { 586 return ec_imexport_types(selection); 587 } 588 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 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 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 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 824 const OSSL_PARAM *ec_settable_params(void *provctx) 825 { 826 return ec_known_settable_params; 827 } 828 829 static 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 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 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 895 const OSSL_PARAM *sm2_settable_params(ossl_unused void *provctx) 896 { 897 return sm2_known_settable_params; 898 } 899 900 static 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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