1/* 2 * Copyright 2019-2022 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#include <openssl/crypto.h> 11#include <openssl/evp.h> 12#include <openssl/err.h> 13#include "internal/cryptlib.h" 14#include "internal/refcount.h" 15#include "internal/provider.h" 16#include "internal/core.h" 17#include "internal/numbers.h" /* includes SIZE_MAX */ 18#include "crypto/evp.h" 19#include "evp_local.h" 20 21static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov) 22{ 23 EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH)); 24 25 if (exchange == NULL) { 26 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 27 return NULL; 28 } 29 30 exchange->lock = CRYPTO_THREAD_lock_new(); 31 if (exchange->lock == NULL) { 32 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 33 OPENSSL_free(exchange); 34 return NULL; 35 } 36 exchange->prov = prov; 37 ossl_provider_up_ref(prov); 38 exchange->refcnt = 1; 39 40 return exchange; 41} 42 43static void *evp_keyexch_from_algorithm(int name_id, 44 const OSSL_ALGORITHM *algodef, 45 OSSL_PROVIDER *prov) 46{ 47 const OSSL_DISPATCH *fns = algodef->implementation; 48 EVP_KEYEXCH *exchange = NULL; 49 int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0; 50 51 if ((exchange = evp_keyexch_new(prov)) == NULL) { 52 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 53 goto err; 54 } 55 56 exchange->name_id = name_id; 57 if ((exchange->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) 58 goto err; 59 exchange->description = algodef->algorithm_description; 60 61 for (; fns->function_id != 0; fns++) { 62 switch (fns->function_id) { 63 case OSSL_FUNC_KEYEXCH_NEWCTX: 64 if (exchange->newctx != NULL) 65 break; 66 exchange->newctx = OSSL_FUNC_keyexch_newctx(fns); 67 fncnt++; 68 break; 69 case OSSL_FUNC_KEYEXCH_INIT: 70 if (exchange->init != NULL) 71 break; 72 exchange->init = OSSL_FUNC_keyexch_init(fns); 73 fncnt++; 74 break; 75 case OSSL_FUNC_KEYEXCH_SET_PEER: 76 if (exchange->set_peer != NULL) 77 break; 78 exchange->set_peer = OSSL_FUNC_keyexch_set_peer(fns); 79 break; 80 case OSSL_FUNC_KEYEXCH_DERIVE: 81 if (exchange->derive != NULL) 82 break; 83 exchange->derive = OSSL_FUNC_keyexch_derive(fns); 84 fncnt++; 85 break; 86 case OSSL_FUNC_KEYEXCH_FREECTX: 87 if (exchange->freectx != NULL) 88 break; 89 exchange->freectx = OSSL_FUNC_keyexch_freectx(fns); 90 fncnt++; 91 break; 92 case OSSL_FUNC_KEYEXCH_DUPCTX: 93 if (exchange->dupctx != NULL) 94 break; 95 exchange->dupctx = OSSL_FUNC_keyexch_dupctx(fns); 96 break; 97 case OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS: 98 if (exchange->get_ctx_params != NULL) 99 break; 100 exchange->get_ctx_params = OSSL_FUNC_keyexch_get_ctx_params(fns); 101 gparamfncnt++; 102 break; 103 case OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS: 104 if (exchange->gettable_ctx_params != NULL) 105 break; 106 exchange->gettable_ctx_params 107 = OSSL_FUNC_keyexch_gettable_ctx_params(fns); 108 gparamfncnt++; 109 break; 110 case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS: 111 if (exchange->set_ctx_params != NULL) 112 break; 113 exchange->set_ctx_params = OSSL_FUNC_keyexch_set_ctx_params(fns); 114 sparamfncnt++; 115 break; 116 case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS: 117 if (exchange->settable_ctx_params != NULL) 118 break; 119 exchange->settable_ctx_params 120 = OSSL_FUNC_keyexch_settable_ctx_params(fns); 121 sparamfncnt++; 122 break; 123 } 124 } 125 if (fncnt != 4 126 || (gparamfncnt != 0 && gparamfncnt != 2) 127 || (sparamfncnt != 0 && sparamfncnt != 2)) { 128 /* 129 * In order to be a consistent set of functions we must have at least 130 * a complete set of "exchange" functions: init, derive, newctx, 131 * and freectx. The set_ctx_params and settable_ctx_params functions are 132 * optional, but if one of them is present then the other one must also 133 * be present. Same goes for get_ctx_params and gettable_ctx_params. 134 * The dupctx and set_peer functions are optional. 135 */ 136 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); 137 goto err; 138 } 139 140 return exchange; 141 142 err: 143 EVP_KEYEXCH_free(exchange); 144 return NULL; 145} 146 147void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange) 148{ 149 int i; 150 151 if (exchange == NULL) 152 return; 153 CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock); 154 if (i > 0) 155 return; 156 OPENSSL_free(exchange->type_name); 157 ossl_provider_free(exchange->prov); 158 CRYPTO_THREAD_lock_free(exchange->lock); 159 OPENSSL_free(exchange); 160} 161 162int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange) 163{ 164 int ref = 0; 165 166 CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock); 167 return 1; 168} 169 170OSSL_PROVIDER *EVP_KEYEXCH_get0_provider(const EVP_KEYEXCH *exchange) 171{ 172 return exchange->prov; 173} 174 175EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, 176 const char *properties) 177{ 178 return evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties, 179 evp_keyexch_from_algorithm, 180 (int (*)(void *))EVP_KEYEXCH_up_ref, 181 (void (*)(void *))EVP_KEYEXCH_free); 182} 183 184EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov, 185 const char *algorithm, 186 const char *properties) 187{ 188 return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYEXCH, 189 algorithm, properties, 190 evp_keyexch_from_algorithm, 191 (int (*)(void *))EVP_KEYEXCH_up_ref, 192 (void (*)(void *))EVP_KEYEXCH_free); 193} 194 195int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) 196{ 197 return EVP_PKEY_derive_init_ex(ctx, NULL); 198} 199 200int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) 201{ 202 int ret; 203 void *provkey = NULL; 204 EVP_KEYEXCH *exchange = NULL; 205 EVP_KEYMGMT *tmp_keymgmt = NULL; 206 const OSSL_PROVIDER *tmp_prov = NULL; 207 const char *supported_exch = NULL; 208 int iter; 209 210 if (ctx == NULL) { 211 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); 212 return -2; 213 } 214 215 evp_pkey_ctx_free_old_ops(ctx); 216 ctx->operation = EVP_PKEY_OP_DERIVE; 217 218 ERR_set_mark(); 219 220 if (evp_pkey_ctx_is_legacy(ctx)) 221 goto legacy; 222 223 /* 224 * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create 225 * a blank one. 226 */ 227 if (ctx->pkey == NULL) { 228 EVP_PKEY *pkey = EVP_PKEY_new(); 229 230 if (pkey == NULL 231 || !EVP_PKEY_set_type_by_keymgmt(pkey, ctx->keymgmt) 232 || (pkey->keydata = evp_keymgmt_newdata(ctx->keymgmt)) == NULL) { 233 ERR_clear_last_mark(); 234 EVP_PKEY_free(pkey); 235 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 236 goto err; 237 } 238 ctx->pkey = pkey; 239 } 240 241 /* 242 * Try to derive the supported exch from |ctx->keymgmt|. 243 */ 244 if (!ossl_assert(ctx->pkey->keymgmt == NULL 245 || ctx->pkey->keymgmt == ctx->keymgmt)) { 246 ERR_clear_last_mark(); 247 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); 248 goto err; 249 } 250 supported_exch = evp_keymgmt_util_query_operation_name(ctx->keymgmt, 251 OSSL_OP_KEYEXCH); 252 if (supported_exch == NULL) { 253 ERR_clear_last_mark(); 254 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 255 goto err; 256 } 257 258 259 /* 260 * We perform two iterations: 261 * 262 * 1. Do the normal exchange fetch, using the fetching data given by 263 * the EVP_PKEY_CTX. 264 * 2. Do the provider specific exchange fetch, from the same provider 265 * as |ctx->keymgmt| 266 * 267 * We then try to fetch the keymgmt from the same provider as the 268 * exchange, and try to export |ctx->pkey| to that keymgmt (when 269 * this keymgmt happens to be the same as |ctx->keymgmt|, the export 270 * is a no-op, but we call it anyway to not complicate the code even 271 * more). 272 * If the export call succeeds (returns a non-NULL provider key pointer), 273 * we're done and can perform the operation itself. If not, we perform 274 * the second iteration, or jump to legacy. 275 */ 276 for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { 277 EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; 278 279 /* 280 * If we're on the second iteration, free the results from the first. 281 * They are NULL on the first iteration, so no need to check what 282 * iteration we're on. 283 */ 284 EVP_KEYEXCH_free(exchange); 285 EVP_KEYMGMT_free(tmp_keymgmt); 286 287 switch (iter) { 288 case 1: 289 exchange = 290 EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery); 291 if (exchange != NULL) 292 tmp_prov = EVP_KEYEXCH_get0_provider(exchange); 293 break; 294 case 2: 295 tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt); 296 exchange = 297 evp_keyexch_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, 298 supported_exch, ctx->propquery); 299 if (exchange == NULL) 300 goto legacy; 301 break; 302 } 303 if (exchange == NULL) 304 continue; 305 306 /* 307 * Ensure that the key is provided, either natively, or as a cached 308 * export. We start by fetching the keymgmt with the same name as 309 * |ctx->keymgmt|, but from the provider of the exchange method, using 310 * the same property query as when fetching the exchange method. 311 * With the keymgmt we found (if we did), we try to export |ctx->pkey| 312 * to it (evp_pkey_export_to_provider() is smart enough to only actually 313 * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) 314 */ 315 tmp_keymgmt_tofree = tmp_keymgmt = 316 evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, 317 EVP_KEYMGMT_get0_name(ctx->keymgmt), 318 ctx->propquery); 319 if (tmp_keymgmt != NULL) 320 provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, 321 &tmp_keymgmt, ctx->propquery); 322 if (tmp_keymgmt == NULL) 323 EVP_KEYMGMT_free(tmp_keymgmt_tofree); 324 } 325 326 if (provkey == NULL) { 327 EVP_KEYEXCH_free(exchange); 328 goto legacy; 329 } 330 331 ERR_pop_to_mark(); 332 333 /* No more legacy from here down to legacy: */ 334 335 ctx->op.kex.exchange = exchange; 336 ctx->op.kex.algctx = exchange->newctx(ossl_provider_ctx(exchange->prov)); 337 if (ctx->op.kex.algctx == NULL) { 338 /* The provider key can stay in the cache */ 339 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 340 goto err; 341 } 342 ret = exchange->init(ctx->op.kex.algctx, provkey, params); 343 344 EVP_KEYMGMT_free(tmp_keymgmt); 345 return ret ? 1 : 0; 346 err: 347 evp_pkey_ctx_free_old_ops(ctx); 348 ctx->operation = EVP_PKEY_OP_UNDEFINED; 349 EVP_KEYMGMT_free(tmp_keymgmt); 350 return 0; 351 352 legacy: 353 /* 354 * If we don't have the full support we need with provided methods, 355 * let's go see if legacy does. 356 */ 357 ERR_pop_to_mark(); 358 359#ifdef FIPS_MODULE 360 return 0; 361#else 362 if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) { 363 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 364 return -2; 365 } 366 367 if (ctx->pmeth->derive_init == NULL) 368 return 1; 369 ret = ctx->pmeth->derive_init(ctx); 370 if (ret <= 0) 371 ctx->operation = EVP_PKEY_OP_UNDEFINED; 372 EVP_KEYMGMT_free(tmp_keymgmt); 373 return ret; 374#endif 375} 376 377int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer, 378 int validate_peer) 379{ 380 int ret = 0, check; 381 void *provkey = NULL; 382 EVP_PKEY_CTX *check_ctx = NULL; 383 EVP_KEYMGMT *tmp_keymgmt = NULL, *tmp_keymgmt_tofree = NULL; 384 385 if (ctx == NULL) { 386 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); 387 return -1; 388 } 389 390 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.algctx == NULL) 391 goto legacy; 392 393 if (ctx->op.kex.exchange->set_peer == NULL) { 394 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 395 return -2; 396 } 397 398 if (validate_peer) { 399 check_ctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, peer, ctx->propquery); 400 if (check_ctx == NULL) 401 return -1; 402 check = EVP_PKEY_public_check(check_ctx); 403 EVP_PKEY_CTX_free(check_ctx); 404 if (check <= 0) 405 return -1; 406 } 407 408 /* 409 * Ensure that the |peer| is provided, either natively, or as a cached 410 * export. We start by fetching the keymgmt with the same name as 411 * |ctx->keymgmt|, but from the provider of the exchange method, using 412 * the same property query as when fetching the exchange method. 413 * With the keymgmt we found (if we did), we try to export |peer| 414 * to it (evp_pkey_export_to_provider() is smart enough to only actually 415 * export it if |tmp_keymgmt| is different from |peer|'s keymgmt) 416 */ 417 tmp_keymgmt_tofree = tmp_keymgmt = 418 evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *) 419 EVP_KEYEXCH_get0_provider(ctx->op.kex.exchange), 420 EVP_KEYMGMT_get0_name(ctx->keymgmt), 421 ctx->propquery); 422 if (tmp_keymgmt != NULL) 423 provkey = evp_pkey_export_to_provider(peer, ctx->libctx, 424 &tmp_keymgmt, ctx->propquery); 425 EVP_KEYMGMT_free(tmp_keymgmt_tofree); 426 427 /* 428 * If making the key provided wasn't possible, legacy may be able to pick 429 * it up 430 */ 431 if (provkey == NULL) 432 goto legacy; 433 return ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey); 434 435 legacy: 436#ifdef FIPS_MODULE 437 return ret; 438#else 439 if (ctx->pmeth == NULL 440 || !(ctx->pmeth->derive != NULL 441 || ctx->pmeth->encrypt != NULL 442 || ctx->pmeth->decrypt != NULL) 443 || ctx->pmeth->ctrl == NULL) { 444 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 445 return -2; 446 } 447 if (ctx->operation != EVP_PKEY_OP_DERIVE 448 && ctx->operation != EVP_PKEY_OP_ENCRYPT 449 && ctx->operation != EVP_PKEY_OP_DECRYPT) { 450 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 451 return -1; 452 } 453 454 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); 455 456 if (ret <= 0) 457 return ret; 458 459 if (ret == 2) 460 return 1; 461 462 if (ctx->pkey == NULL) { 463 ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); 464 return -1; 465 } 466 467 if (ctx->pkey->type != peer->type) { 468 ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); 469 return -1; 470 } 471 472 /* 473 * For clarity. The error is if parameters in peer are 474 * present (!missing) but don't match. EVP_PKEY_parameters_eq may return 475 * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 476 * (different key types) is impossible here because it is checked earlier. 477 * -2 is OK for us here, as well as 1, so we can check for 0 only. 478 */ 479 if (!EVP_PKEY_missing_parameters(peer) && 480 !EVP_PKEY_parameters_eq(ctx->pkey, peer)) { 481 ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS); 482 return -1; 483 } 484 485 EVP_PKEY_free(ctx->peerkey); 486 ctx->peerkey = peer; 487 488 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); 489 490 if (ret <= 0) { 491 ctx->peerkey = NULL; 492 return ret; 493 } 494 495 EVP_PKEY_up_ref(peer); 496 return 1; 497#endif 498} 499 500int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) 501{ 502 return EVP_PKEY_derive_set_peer_ex(ctx, peer, 1); 503} 504 505int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) 506{ 507 int ret; 508 509 if (ctx == NULL || pkeylen == NULL) { 510 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); 511 return -1; 512 } 513 514 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { 515 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 516 return -1; 517 } 518 519 if (ctx->op.kex.algctx == NULL) 520 goto legacy; 521 522 ret = ctx->op.kex.exchange->derive(ctx->op.kex.algctx, key, pkeylen, 523 key != NULL ? *pkeylen : 0); 524 525 return ret; 526 legacy: 527 if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) { 528 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 529 return -2; 530 } 531 532 M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) 533 return ctx->pmeth->derive(ctx, key, pkeylen); 534} 535 536int evp_keyexch_get_number(const EVP_KEYEXCH *keyexch) 537{ 538 return keyexch->name_id; 539} 540 541const char *EVP_KEYEXCH_get0_name(const EVP_KEYEXCH *keyexch) 542{ 543 return keyexch->type_name; 544} 545 546const char *EVP_KEYEXCH_get0_description(const EVP_KEYEXCH *keyexch) 547{ 548 return keyexch->description; 549} 550 551int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name) 552{ 553 return keyexch != NULL 554 && evp_is_a(keyexch->prov, keyexch->name_id, NULL, name); 555} 556 557void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx, 558 void (*fn)(EVP_KEYEXCH *keyexch, void *arg), 559 void *arg) 560{ 561 evp_generic_do_all(libctx, OSSL_OP_KEYEXCH, 562 (void (*)(void *, void *))fn, arg, 563 evp_keyexch_from_algorithm, 564 (int (*)(void *))EVP_KEYEXCH_up_ref, 565 (void (*)(void *))EVP_KEYEXCH_free); 566} 567 568int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch, 569 void (*fn)(const char *name, void *data), 570 void *data) 571{ 572 if (keyexch->prov != NULL) 573 return evp_names_do_all(keyexch->prov, keyexch->name_id, fn, data); 574 575 return 1; 576} 577 578const OSSL_PARAM *EVP_KEYEXCH_gettable_ctx_params(const EVP_KEYEXCH *keyexch) 579{ 580 void *provctx; 581 582 if (keyexch == NULL || keyexch->gettable_ctx_params == NULL) 583 return NULL; 584 585 provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(keyexch)); 586 return keyexch->gettable_ctx_params(NULL, provctx); 587} 588 589const OSSL_PARAM *EVP_KEYEXCH_settable_ctx_params(const EVP_KEYEXCH *keyexch) 590{ 591 void *provctx; 592 593 if (keyexch == NULL || keyexch->settable_ctx_params == NULL) 594 return NULL; 595 provctx = ossl_provider_ctx(EVP_KEYEXCH_get0_provider(keyexch)); 596 return keyexch->settable_ctx_params(NULL, provctx); 597} 598