1 /* 2 * Copyright 2019-2023 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 * DH 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> /* strcmp */ 17 #include <openssl/core_dispatch.h> 18 #include <openssl/core_names.h> 19 #include <openssl/bn.h> 20 #include <openssl/err.h> 21 #include "prov/implementations.h" 22 #include "prov/providercommon.h" 23 #include "prov/provider_ctx.h" 24 #include "crypto/dh.h" 25 #include "internal/sizes.h" 26 27 static OSSL_FUNC_keymgmt_new_fn dh_newdata; 28 static OSSL_FUNC_keymgmt_free_fn dh_freedata; 29 static OSSL_FUNC_keymgmt_gen_init_fn dh_gen_init; 30 static OSSL_FUNC_keymgmt_gen_init_fn dhx_gen_init; 31 static OSSL_FUNC_keymgmt_gen_set_template_fn dh_gen_set_template; 32 static OSSL_FUNC_keymgmt_gen_set_params_fn dh_gen_set_params; 33 static OSSL_FUNC_keymgmt_gen_settable_params_fn dh_gen_settable_params; 34 static OSSL_FUNC_keymgmt_gen_fn dh_gen; 35 static OSSL_FUNC_keymgmt_gen_cleanup_fn dh_gen_cleanup; 36 static OSSL_FUNC_keymgmt_load_fn dh_load; 37 static OSSL_FUNC_keymgmt_get_params_fn dh_get_params; 38 static OSSL_FUNC_keymgmt_gettable_params_fn dh_gettable_params; 39 static OSSL_FUNC_keymgmt_set_params_fn dh_set_params; 40 static OSSL_FUNC_keymgmt_settable_params_fn dh_settable_params; 41 static OSSL_FUNC_keymgmt_has_fn dh_has; 42 static OSSL_FUNC_keymgmt_match_fn dh_match; 43 static OSSL_FUNC_keymgmt_validate_fn dh_validate; 44 static OSSL_FUNC_keymgmt_import_fn dh_import; 45 static OSSL_FUNC_keymgmt_import_types_fn dh_import_types; 46 static OSSL_FUNC_keymgmt_export_fn dh_export; 47 static OSSL_FUNC_keymgmt_export_types_fn dh_export_types; 48 static OSSL_FUNC_keymgmt_dup_fn dh_dup; 49 50 #define DH_POSSIBLE_SELECTIONS \ 51 (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) 52 53 struct dh_gen_ctx { 54 OSSL_LIB_CTX *libctx; 55 56 FFC_PARAMS *ffc_params; 57 int selection; 58 /* All these parameters are used for parameter generation only */ 59 /* If there is a group name then the remaining parameters are not needed */ 60 int group_nid; 61 size_t pbits; 62 size_t qbits; 63 unsigned char *seed; /* optional FIPS186-4 param for testing */ 64 size_t seedlen; 65 int gindex; /* optional FIPS186-4 generator index (ignored if -1) */ 66 int gen_type; /* see dhtype2id */ 67 int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */ 68 int pcounter; 69 int hindex; 70 int priv_len; 71 72 char *mdname; 73 char *mdprops; 74 OSSL_CALLBACK *cb; 75 void *cbarg; 76 int dh_type; 77 }; 78 79 static int dh_gen_type_name2id_w_default(const char *name, int type) 80 { 81 if (strcmp(name, "default") == 0) { 82 #ifdef FIPS_MODULE 83 if (type == DH_FLAG_TYPE_DHX) 84 return DH_PARAMGEN_TYPE_FIPS_186_4; 85 86 return DH_PARAMGEN_TYPE_GROUP; 87 #else 88 if (type == DH_FLAG_TYPE_DHX) 89 return DH_PARAMGEN_TYPE_FIPS_186_2; 90 91 return DH_PARAMGEN_TYPE_GENERATOR; 92 #endif 93 } 94 95 return ossl_dh_gen_type_name2id(name, type); 96 } 97 98 static void *dh_newdata(void *provctx) 99 { 100 DH *dh = NULL; 101 102 if (ossl_prov_is_running()) { 103 dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx)); 104 if (dh != NULL) { 105 DH_clear_flags(dh, DH_FLAG_TYPE_MASK); 106 DH_set_flags(dh, DH_FLAG_TYPE_DH); 107 } 108 } 109 return dh; 110 } 111 112 static void *dhx_newdata(void *provctx) 113 { 114 DH *dh = NULL; 115 116 dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx)); 117 if (dh != NULL) { 118 DH_clear_flags(dh, DH_FLAG_TYPE_MASK); 119 DH_set_flags(dh, DH_FLAG_TYPE_DHX); 120 } 121 return dh; 122 } 123 124 static void dh_freedata(void *keydata) 125 { 126 DH_free(keydata); 127 } 128 129 static int dh_has(const void *keydata, int selection) 130 { 131 const DH *dh = keydata; 132 int ok = 1; 133 134 if (!ossl_prov_is_running() || dh == NULL) 135 return 0; 136 if ((selection & DH_POSSIBLE_SELECTIONS) == 0) 137 return 1; /* the selection is not missing */ 138 139 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 140 ok = ok && (DH_get0_pub_key(dh) != NULL); 141 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 142 ok = ok && (DH_get0_priv_key(dh) != NULL); 143 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) 144 ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL); 145 return ok; 146 } 147 148 static int dh_match(const void *keydata1, const void *keydata2, int selection) 149 { 150 const DH *dh1 = keydata1; 151 const DH *dh2 = keydata2; 152 int ok = 1; 153 154 if (!ossl_prov_is_running()) 155 return 0; 156 157 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 158 int key_checked = 0; 159 160 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { 161 const BIGNUM *pa = DH_get0_pub_key(dh1); 162 const BIGNUM *pb = DH_get0_pub_key(dh2); 163 164 if (pa != NULL && pb != NULL) { 165 ok = ok && BN_cmp(pa, pb) == 0; 166 key_checked = 1; 167 } 168 } 169 if (!key_checked 170 && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { 171 const BIGNUM *pa = DH_get0_priv_key(dh1); 172 const BIGNUM *pb = DH_get0_priv_key(dh2); 173 174 if (pa != NULL && pb != NULL) { 175 ok = ok && BN_cmp(pa, pb) == 0; 176 key_checked = 1; 177 } 178 } 179 ok = ok && key_checked; 180 } 181 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { 182 FFC_PARAMS *dhparams1 = ossl_dh_get0_params((DH *)dh1); 183 FFC_PARAMS *dhparams2 = ossl_dh_get0_params((DH *)dh2); 184 185 ok = ok && ossl_ffc_params_cmp(dhparams1, dhparams2, 1); 186 } 187 return ok; 188 } 189 190 static int dh_import(void *keydata, int selection, const OSSL_PARAM params[]) 191 { 192 DH *dh = keydata; 193 int ok = 1; 194 195 if (!ossl_prov_is_running() || dh == NULL) 196 return 0; 197 198 if ((selection & DH_POSSIBLE_SELECTIONS) == 0) 199 return 0; 200 201 /* a key without parameters is meaningless */ 202 ok = ok && ossl_dh_params_fromdata(dh, params); 203 204 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 205 int include_private = 206 selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; 207 208 ok = ok && ossl_dh_key_fromdata(dh, params, include_private); 209 } 210 211 return ok; 212 } 213 214 static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, 215 void *cbarg) 216 { 217 DH *dh = keydata; 218 OSSL_PARAM_BLD *tmpl = NULL; 219 OSSL_PARAM *params = NULL; 220 int ok = 1; 221 222 if (!ossl_prov_is_running() || dh == NULL) 223 return 0; 224 225 tmpl = OSSL_PARAM_BLD_new(); 226 if (tmpl == NULL) 227 return 0; 228 229 if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) 230 ok = ok && ossl_dh_params_todata(dh, tmpl, NULL); 231 232 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 233 int include_private = 234 selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; 235 236 ok = ok && ossl_dh_key_todata(dh, tmpl, NULL, include_private); 237 } 238 239 if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) { 240 ok = 0; 241 goto err; 242 } 243 244 ok = param_cb(params, cbarg); 245 OSSL_PARAM_free(params); 246 err: 247 OSSL_PARAM_BLD_free(tmpl); 248 return ok; 249 } 250 251 /* IMEXPORT = IMPORT + EXPORT */ 252 253 # define DH_IMEXPORTABLE_PARAMETERS \ 254 OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \ 255 OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \ 256 OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \ 257 OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \ 258 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \ 259 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \ 260 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \ 261 OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), \ 262 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), \ 263 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0) 264 # define DH_IMEXPORTABLE_PUBLIC_KEY \ 265 OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0) 266 # define DH_IMEXPORTABLE_PRIVATE_KEY \ 267 OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0) 268 static const OSSL_PARAM dh_all_types[] = { 269 DH_IMEXPORTABLE_PARAMETERS, 270 DH_IMEXPORTABLE_PUBLIC_KEY, 271 DH_IMEXPORTABLE_PRIVATE_KEY, 272 OSSL_PARAM_END 273 }; 274 static const OSSL_PARAM dh_parameter_types[] = { 275 DH_IMEXPORTABLE_PARAMETERS, 276 OSSL_PARAM_END 277 }; 278 static const OSSL_PARAM dh_key_types[] = { 279 DH_IMEXPORTABLE_PUBLIC_KEY, 280 DH_IMEXPORTABLE_PRIVATE_KEY, 281 OSSL_PARAM_END 282 }; 283 static const OSSL_PARAM *dh_types[] = { 284 NULL, /* Index 0 = none of them */ 285 dh_parameter_types, /* Index 1 = parameter types */ 286 dh_key_types, /* Index 2 = key types */ 287 dh_all_types /* Index 3 = 1 + 2 */ 288 }; 289 290 static const OSSL_PARAM *dh_imexport_types(int selection) 291 { 292 int type_select = 0; 293 294 if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) 295 type_select += 1; 296 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) 297 type_select += 2; 298 return dh_types[type_select]; 299 } 300 301 static const OSSL_PARAM *dh_import_types(int selection) 302 { 303 return dh_imexport_types(selection); 304 } 305 306 static const OSSL_PARAM *dh_export_types(int selection) 307 { 308 return dh_imexport_types(selection); 309 } 310 311 static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[]) 312 { 313 DH *dh = key; 314 OSSL_PARAM *p; 315 316 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL 317 && !OSSL_PARAM_set_int(p, DH_bits(dh))) 318 return 0; 319 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL 320 && !OSSL_PARAM_set_int(p, DH_security_bits(dh))) 321 return 0; 322 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL 323 && !OSSL_PARAM_set_int(p, DH_size(dh))) 324 return 0; 325 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { 326 if (p->data_type != OSSL_PARAM_OCTET_STRING) 327 return 0; 328 p->return_size = ossl_dh_key2buf(dh, (unsigned char **)&p->data, 329 p->data_size, 0); 330 if (p->return_size == 0) 331 return 0; 332 } 333 334 return ossl_dh_params_todata(dh, NULL, params) 335 && ossl_dh_key_todata(dh, NULL, params, 1); 336 } 337 338 static const OSSL_PARAM dh_params[] = { 339 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), 340 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), 341 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), 342 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 343 DH_IMEXPORTABLE_PARAMETERS, 344 DH_IMEXPORTABLE_PUBLIC_KEY, 345 DH_IMEXPORTABLE_PRIVATE_KEY, 346 OSSL_PARAM_END 347 }; 348 349 static const OSSL_PARAM *dh_gettable_params(void *provctx) 350 { 351 return dh_params; 352 } 353 354 static const OSSL_PARAM dh_known_settable_params[] = { 355 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 356 OSSL_PARAM_END 357 }; 358 359 static const OSSL_PARAM *dh_settable_params(void *provctx) 360 { 361 return dh_known_settable_params; 362 } 363 364 static int dh_set_params(void *key, const OSSL_PARAM params[]) 365 { 366 DH *dh = key; 367 const OSSL_PARAM *p; 368 369 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); 370 if (p != NULL 371 && (p->data_type != OSSL_PARAM_OCTET_STRING 372 || !ossl_dh_buf2key(dh, p->data, p->data_size))) 373 return 0; 374 375 return 1; 376 } 377 378 static int dh_validate_public(const DH *dh, int checktype) 379 { 380 const BIGNUM *pub_key = NULL; 381 int res = 0; 382 383 DH_get0_key(dh, &pub_key, NULL); 384 if (pub_key == NULL) 385 return 0; 386 387 /* The partial test is only valid for named group's with q = (p - 1) / 2 */ 388 if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK 389 && ossl_dh_is_named_safe_prime_group(dh)) 390 return ossl_dh_check_pub_key_partial(dh, pub_key, &res); 391 392 return DH_check_pub_key(dh, pub_key, &res); 393 } 394 395 static int dh_validate_private(const DH *dh) 396 { 397 int status = 0; 398 const BIGNUM *priv_key = NULL; 399 400 DH_get0_key(dh, NULL, &priv_key); 401 if (priv_key == NULL) 402 return 0; 403 return ossl_dh_check_priv_key(dh, priv_key, &status);; 404 } 405 406 static int dh_validate(const void *keydata, int selection, int checktype) 407 { 408 const DH *dh = keydata; 409 int ok = 1; 410 411 if (!ossl_prov_is_running()) 412 return 0; 413 414 if ((selection & DH_POSSIBLE_SELECTIONS) == 0) 415 return 1; /* nothing to validate */ 416 417 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { 418 /* 419 * Both of these functions check parameters. DH_check_params_ex() 420 * performs a lightweight check (e.g. it does not check that p is a 421 * safe prime) 422 */ 423 if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK) 424 ok = ok && DH_check_params_ex(dh); 425 else 426 ok = ok && DH_check_ex(dh); 427 } 428 429 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 430 ok = ok && dh_validate_public(dh, checktype); 431 432 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 433 ok = ok && dh_validate_private(dh); 434 435 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) 436 == OSSL_KEYMGMT_SELECT_KEYPAIR) 437 ok = ok && ossl_dh_check_pairwise(dh); 438 return ok; 439 } 440 441 static void *dh_gen_init_base(void *provctx, int selection, 442 const OSSL_PARAM params[], int type) 443 { 444 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx); 445 struct dh_gen_ctx *gctx = NULL; 446 447 if (!ossl_prov_is_running()) 448 return NULL; 449 450 if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR 451 | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0) 452 return NULL; 453 454 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) { 455 gctx->selection = selection; 456 gctx->libctx = libctx; 457 gctx->pbits = 2048; 458 gctx->qbits = 224; 459 gctx->mdname = NULL; 460 #ifdef FIPS_MODULE 461 gctx->gen_type = (type == DH_FLAG_TYPE_DHX) 462 ? DH_PARAMGEN_TYPE_FIPS_186_4 463 : DH_PARAMGEN_TYPE_GROUP; 464 #else 465 gctx->gen_type = (type == DH_FLAG_TYPE_DHX) 466 ? DH_PARAMGEN_TYPE_FIPS_186_2 467 : DH_PARAMGEN_TYPE_GENERATOR; 468 #endif 469 gctx->gindex = -1; 470 gctx->hindex = 0; 471 gctx->pcounter = -1; 472 gctx->generator = DH_GENERATOR_2; 473 gctx->dh_type = type; 474 } 475 if (!dh_gen_set_params(gctx, params)) { 476 OPENSSL_free(gctx); 477 gctx = NULL; 478 } 479 return gctx; 480 } 481 482 static void *dh_gen_init(void *provctx, int selection, 483 const OSSL_PARAM params[]) 484 { 485 return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DH); 486 } 487 488 static void *dhx_gen_init(void *provctx, int selection, 489 const OSSL_PARAM params[]) 490 { 491 return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DHX); 492 } 493 494 static int dh_gen_set_template(void *genctx, void *templ) 495 { 496 struct dh_gen_ctx *gctx = genctx; 497 DH *dh = templ; 498 499 if (!ossl_prov_is_running() || gctx == NULL || dh == NULL) 500 return 0; 501 gctx->ffc_params = ossl_dh_get0_params(dh); 502 return 1; 503 } 504 505 static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed, 506 size_t seedlen) 507 { 508 OPENSSL_clear_free(gctx->seed, gctx->seedlen); 509 gctx->seed = NULL; 510 gctx->seedlen = 0; 511 if (seed != NULL && seedlen > 0) { 512 gctx->seed = OPENSSL_memdup(seed, seedlen); 513 if (gctx->seed == NULL) 514 return 0; 515 gctx->seedlen = seedlen; 516 } 517 return 1; 518 } 519 520 static int dh_gen_common_set_params(void *genctx, const OSSL_PARAM params[]) 521 { 522 struct dh_gen_ctx *gctx = genctx; 523 const OSSL_PARAM *p; 524 525 if (gctx == NULL) 526 return 0; 527 if (params == NULL) 528 return 1; 529 530 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE); 531 if (p != NULL) { 532 if (p->data_type != OSSL_PARAM_UTF8_STRING 533 || ((gctx->gen_type = 534 dh_gen_type_name2id_w_default(p->data, gctx->dh_type)) == -1)) { 535 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); 536 return 0; 537 } 538 } 539 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); 540 if (p != NULL) { 541 const DH_NAMED_GROUP *group = NULL; 542 543 if (p->data_type != OSSL_PARAM_UTF8_STRING 544 || p->data == NULL 545 || (group = ossl_ffc_name_to_dh_named_group(p->data)) == NULL 546 || ((gctx->group_nid = 547 ossl_ffc_named_group_get_uid(group)) == NID_undef)) { 548 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); 549 return 0; 550 } 551 } 552 if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL 553 && !OSSL_PARAM_get_size_t(p, &gctx->pbits)) 554 return 0; 555 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN); 556 if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len)) 557 return 0; 558 return 1; 559 } 560 561 static const OSSL_PARAM *dh_gen_settable_params(ossl_unused void *genctx, 562 ossl_unused void *provctx) 563 { 564 static const OSSL_PARAM dh_gen_settable[] = { 565 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0), 566 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), 567 OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), 568 OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL), 569 OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_GENERATOR, NULL), 570 OSSL_PARAM_END 571 }; 572 return dh_gen_settable; 573 } 574 575 static const OSSL_PARAM *dhx_gen_settable_params(ossl_unused void *genctx, 576 ossl_unused void *provctx) 577 { 578 static const OSSL_PARAM dhx_gen_settable[] = { 579 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0), 580 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), 581 OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), 582 OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL), 583 OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL), 584 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0), 585 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0), 586 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), 587 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), 588 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), 589 OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), 590 OSSL_PARAM_END 591 }; 592 return dhx_gen_settable; 593 } 594 595 static int dhx_gen_set_params(void *genctx, const OSSL_PARAM params[]) 596 { 597 struct dh_gen_ctx *gctx = genctx; 598 const OSSL_PARAM *p; 599 600 if (!dh_gen_common_set_params(genctx, params)) 601 return 0; 602 603 /* Parameters related to fips186-4 and fips186-2 */ 604 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX); 605 if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex)) 606 return 0; 607 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER); 608 if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter)) 609 return 0; 610 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H); 611 if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex)) 612 return 0; 613 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED); 614 if (p != NULL 615 && (p->data_type != OSSL_PARAM_OCTET_STRING 616 || !dh_set_gen_seed(gctx, p->data, p->data_size))) 617 return 0; 618 if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL 619 && !OSSL_PARAM_get_size_t(p, &gctx->qbits)) 620 return 0; 621 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST); 622 if (p != NULL) { 623 if (p->data_type != OSSL_PARAM_UTF8_STRING) 624 return 0; 625 OPENSSL_free(gctx->mdname); 626 gctx->mdname = OPENSSL_strdup(p->data); 627 if (gctx->mdname == NULL) 628 return 0; 629 } 630 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS); 631 if (p != NULL) { 632 if (p->data_type != OSSL_PARAM_UTF8_STRING) 633 return 0; 634 OPENSSL_free(gctx->mdprops); 635 gctx->mdprops = OPENSSL_strdup(p->data); 636 if (gctx->mdprops == NULL) 637 return 0; 638 } 639 640 /* Parameters that are not allowed for DHX */ 641 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR); 642 if (p != NULL) { 643 ERR_raise(ERR_LIB_PROV, ERR_R_UNSUPPORTED); 644 return 0; 645 } 646 return 1; 647 } 648 649 static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[]) 650 { 651 struct dh_gen_ctx *gctx = genctx; 652 const OSSL_PARAM *p; 653 654 if (!dh_gen_common_set_params(genctx, params)) 655 return 0; 656 657 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR); 658 if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator)) 659 return 0; 660 661 /* Parameters that are not allowed for DH */ 662 if (OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX) != NULL 663 || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER) != NULL 664 || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H) != NULL 665 || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED) != NULL 666 || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS) != NULL 667 || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST) != NULL 668 || OSSL_PARAM_locate_const(params, 669 OSSL_PKEY_PARAM_FFC_DIGEST_PROPS) != NULL) { 670 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); 671 return 0; 672 } 673 return 1; 674 } 675 676 static int dh_gencb(int p, int n, BN_GENCB *cb) 677 { 678 struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb); 679 OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; 680 681 params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); 682 params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); 683 684 return gctx->cb(params, gctx->cbarg); 685 } 686 687 static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 688 { 689 int ret = 0; 690 struct dh_gen_ctx *gctx = genctx; 691 DH *dh = NULL; 692 BN_GENCB *gencb = NULL; 693 FFC_PARAMS *ffc; 694 695 if (!ossl_prov_is_running() || gctx == NULL) 696 return NULL; 697 698 /* 699 * If a group name is selected then the type is group regardless of what the 700 * the user selected. This overrides rather than errors for backwards 701 * compatibility. 702 */ 703 if (gctx->group_nid != NID_undef) 704 gctx->gen_type = DH_PARAMGEN_TYPE_GROUP; 705 706 /* For parameter generation - If there is a group name just create it */ 707 if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP 708 && gctx->ffc_params == NULL) { 709 /* Select a named group if there is not one already */ 710 if (gctx->group_nid == NID_undef) 711 gctx->group_nid = ossl_dh_get_named_group_uid_from_size(gctx->pbits); 712 if (gctx->group_nid == NID_undef) 713 return NULL; 714 dh = ossl_dh_new_by_nid_ex(gctx->libctx, gctx->group_nid); 715 if (dh == NULL) 716 return NULL; 717 ffc = ossl_dh_get0_params(dh); 718 } else { 719 dh = ossl_dh_new_ex(gctx->libctx); 720 if (dh == NULL) 721 return NULL; 722 ffc = ossl_dh_get0_params(dh); 723 724 /* Copy the template value if one was passed */ 725 if (gctx->ffc_params != NULL 726 && !ossl_ffc_params_copy(ffc, gctx->ffc_params)) 727 goto end; 728 729 if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen)) 730 goto end; 731 if (gctx->gindex != -1) { 732 ossl_ffc_params_set_gindex(ffc, gctx->gindex); 733 if (gctx->pcounter != -1) 734 ossl_ffc_params_set_pcounter(ffc, gctx->pcounter); 735 } else if (gctx->hindex != 0) { 736 ossl_ffc_params_set_h(ffc, gctx->hindex); 737 } 738 if (gctx->mdname != NULL) { 739 if (!ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops)) 740 goto end; 741 } 742 gctx->cb = osslcb; 743 gctx->cbarg = cbarg; 744 gencb = BN_GENCB_new(); 745 if (gencb != NULL) 746 BN_GENCB_set(gencb, dh_gencb, genctx); 747 748 if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) { 749 /* 750 * NOTE: The old safe prime generator code is not used in fips mode, 751 * (i.e internally it ignores the generator and chooses a named 752 * group based on pbits. 753 */ 754 if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR) 755 ret = DH_generate_parameters_ex(dh, gctx->pbits, 756 gctx->generator, gencb); 757 else 758 ret = ossl_dh_generate_ffc_parameters(dh, gctx->gen_type, 759 gctx->pbits, gctx->qbits, 760 gencb); 761 if (ret <= 0) 762 goto end; 763 } 764 } 765 766 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 767 if (ffc->p == NULL || ffc->g == NULL) 768 goto end; 769 if (gctx->priv_len > 0) 770 DH_set_length(dh, (long)gctx->priv_len); 771 ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY, 772 gctx->gen_type == DH_PARAMGEN_TYPE_FIPS_186_2); 773 if (DH_generate_key(dh) <= 0) 774 goto end; 775 } 776 DH_clear_flags(dh, DH_FLAG_TYPE_MASK); 777 DH_set_flags(dh, gctx->dh_type); 778 779 ret = 1; 780 end: 781 if (ret <= 0) { 782 DH_free(dh); 783 dh = NULL; 784 } 785 BN_GENCB_free(gencb); 786 return dh; 787 } 788 789 static void dh_gen_cleanup(void *genctx) 790 { 791 struct dh_gen_ctx *gctx = genctx; 792 793 if (gctx == NULL) 794 return; 795 796 OPENSSL_free(gctx->mdname); 797 OPENSSL_free(gctx->mdprops); 798 OPENSSL_clear_free(gctx->seed, gctx->seedlen); 799 OPENSSL_free(gctx); 800 } 801 802 static void *dh_load(const void *reference, size_t reference_sz) 803 { 804 DH *dh = NULL; 805 806 if (ossl_prov_is_running() && reference_sz == sizeof(dh)) { 807 /* The contents of the reference is the address to our object */ 808 dh = *(DH **)reference; 809 /* We grabbed, so we detach it */ 810 *(DH **)reference = NULL; 811 return dh; 812 } 813 return NULL; 814 } 815 816 static void *dh_dup(const void *keydata_from, int selection) 817 { 818 if (ossl_prov_is_running()) 819 return ossl_dh_dup(keydata_from, selection); 820 return NULL; 821 } 822 823 const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = { 824 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata }, 825 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init }, 826 { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template }, 827 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params }, 828 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, 829 (void (*)(void))dh_gen_settable_params }, 830 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen }, 831 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup }, 832 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load }, 833 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata }, 834 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params }, 835 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params }, 836 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params }, 837 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params }, 838 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has }, 839 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match }, 840 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate }, 841 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import }, 842 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types }, 843 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export }, 844 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types }, 845 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup }, 846 { 0, NULL } 847 }; 848 849 /* For any DH key, we use the "DH" algorithms regardless of sub-type. */ 850 static const char *dhx_query_operation_name(int operation_id) 851 { 852 return "DH"; 853 } 854 855 const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = { 856 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dhx_newdata }, 857 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dhx_gen_init }, 858 { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template }, 859 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dhx_gen_set_params }, 860 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, 861 (void (*)(void))dhx_gen_settable_params }, 862 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen }, 863 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup }, 864 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load }, 865 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata }, 866 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params }, 867 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params }, 868 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params }, 869 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params }, 870 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has }, 871 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match }, 872 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate }, 873 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import }, 874 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types }, 875 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export }, 876 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types }, 877 { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, 878 (void (*)(void))dhx_query_operation_name }, 879 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup }, 880 { 0, NULL } 881 }; 882