1 /* 2 * Copyright 2020-2026 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 <stdio.h> 11 #include <stdlib.h> 12 #include <openssl/objects.h> 13 #include <openssl/evp.h> 14 #include "internal/cryptlib.h" 15 #include "internal/provider.h" 16 #include "internal/core.h" 17 #include "crypto/evp.h" 18 #include "evp_local.h" 19 20 static void evp_kem_free(void *data) 21 { 22 EVP_KEM_free(data); 23 } 24 25 static int evp_kem_up_ref(void *data) 26 { 27 return EVP_KEM_up_ref(data); 28 } 29 30 static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, 31 const OSSL_PARAM params[], EVP_PKEY *authkey) 32 { 33 int ret = 0; 34 EVP_KEM *kem = NULL; 35 EVP_KEYMGMT *tmp_keymgmt = NULL; 36 const OSSL_PROVIDER *tmp_prov = NULL; 37 void *provkey = NULL, *provauthkey = NULL; 38 const char *supported_kem = NULL; 39 int iter; 40 41 if (ctx == NULL || ctx->keytype == NULL) { 42 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 43 return 0; 44 } 45 46 evp_pkey_ctx_free_old_ops(ctx); 47 ctx->operation = operation; 48 49 if (ctx->pkey == NULL) { 50 ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); 51 goto err; 52 } 53 if (authkey != NULL && authkey->type != ctx->pkey->type) { 54 ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); 55 return 0; 56 } 57 /* 58 * Try to derive the supported kem from |ctx->keymgmt|. 59 */ 60 if (!ossl_assert(ctx->pkey->keymgmt == NULL 61 || ctx->pkey->keymgmt == ctx->keymgmt)) { 62 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); 63 goto err; 64 } 65 supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt, 66 OSSL_OP_KEM); 67 if (supported_kem == NULL) { 68 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 69 goto err; 70 } 71 72 /* 73 * Because we cleared out old ops, we shouldn't need to worry about 74 * checking if kem is already there. 75 * We perform two iterations: 76 * 77 * 1. Do the normal kem fetch, using the fetching data given by 78 * the EVP_PKEY_CTX. 79 * 2. Do the provider specific kem fetch, from the same provider 80 * as |ctx->keymgmt| 81 * 82 * We then try to fetch the keymgmt from the same provider as the 83 * kem, and try to export |ctx->pkey| to that keymgmt (when this 84 * keymgmt happens to be the same as |ctx->keymgmt|, the export is 85 * a no-op, but we call it anyway to not complicate the code even 86 * more). 87 * If the export call succeeds (returns a non-NULL provider key pointer), 88 * we're done and can perform the operation itself. If not, we perform 89 * the second iteration, or jump to legacy. 90 */ 91 for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { 92 EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; 93 94 /* 95 * If we're on the second iteration, free the results from the first. 96 * They are NULL on the first iteration, so no need to check what 97 * iteration we're on. 98 */ 99 EVP_KEM_free(kem); 100 EVP_KEYMGMT_free(tmp_keymgmt); 101 102 switch (iter) { 103 case 1: 104 kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery); 105 if (kem != NULL) 106 tmp_prov = EVP_KEM_get0_provider(kem); 107 break; 108 case 2: 109 tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt); 110 kem = evp_kem_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, 111 supported_kem, ctx->propquery); 112 113 if (kem == NULL) { 114 ERR_raise(ERR_LIB_EVP, 115 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 116 ret = -2; 117 goto err; 118 } 119 } 120 if (kem == NULL) 121 continue; 122 123 /* 124 * Ensure that the key is provided, either natively, or as a cached 125 * export. We start by fetching the keymgmt with the same name as 126 * |ctx->pkey|, but from the provider of the kem method, using the 127 * same property query as when fetching the kem method. 128 * With the keymgmt we found (if we did), we try to export |ctx->pkey| 129 * to it (evp_pkey_export_to_provider() is smart enough to only actually 130 * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) 131 */ 132 tmp_keymgmt_tofree = tmp_keymgmt = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, 133 EVP_KEYMGMT_get0_name(ctx->keymgmt), 134 ctx->propquery); 135 if (tmp_keymgmt != NULL) { 136 provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, 137 &tmp_keymgmt, ctx->propquery); 138 if (provkey != NULL && authkey != NULL) { 139 provauthkey = evp_pkey_export_to_provider(authkey, ctx->libctx, 140 &tmp_keymgmt, 141 ctx->propquery); 142 if (provauthkey == NULL) { 143 EVP_KEM_free(kem); 144 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 145 goto err; 146 } 147 } 148 } 149 if (tmp_keymgmt == NULL) 150 EVP_KEYMGMT_free(tmp_keymgmt_tofree); 151 } 152 153 if (provkey == NULL) { 154 EVP_KEM_free(kem); 155 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 156 goto err; 157 } 158 159 ctx->op.encap.kem = kem; 160 ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov)); 161 if (ctx->op.encap.algctx == NULL) { 162 /* The provider key can stay in the cache */ 163 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 164 goto err; 165 } 166 167 switch (operation) { 168 case EVP_PKEY_OP_ENCAPSULATE: 169 if (provauthkey != NULL && kem->auth_encapsulate_init != NULL) { 170 ret = kem->auth_encapsulate_init(ctx->op.encap.algctx, provkey, 171 provauthkey, params); 172 } else if (provauthkey == NULL && kem->encapsulate_init != NULL) { 173 ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params); 174 } else { 175 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 176 ret = -2; 177 goto err; 178 } 179 break; 180 case EVP_PKEY_OP_DECAPSULATE: 181 if (provauthkey != NULL && kem->auth_decapsulate_init != NULL) { 182 ret = kem->auth_decapsulate_init(ctx->op.encap.algctx, provkey, 183 provauthkey, params); 184 } else if (provauthkey == NULL && kem->decapsulate_init != NULL) { 185 ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params); 186 } else { 187 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 188 ret = -2; 189 goto err; 190 } 191 break; 192 default: 193 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 194 goto err; 195 } 196 197 EVP_KEYMGMT_free(tmp_keymgmt); 198 tmp_keymgmt = NULL; 199 200 if (ret > 0) 201 return 1; 202 err: 203 if (ret <= 0) { 204 evp_pkey_ctx_free_old_ops(ctx); 205 ctx->operation = EVP_PKEY_OP_UNDEFINED; 206 } 207 EVP_KEYMGMT_free(tmp_keymgmt); 208 return ret; 209 } 210 211 int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv, 212 const OSSL_PARAM params[]) 213 { 214 if (authpriv == NULL) 215 return 0; 216 return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, authpriv); 217 } 218 219 int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) 220 { 221 return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, NULL); 222 } 223 224 int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, 225 unsigned char *out, size_t *outlen, 226 unsigned char *secret, size_t *secretlen) 227 { 228 if (ctx == NULL) 229 return 0; 230 231 if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) { 232 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 233 return -1; 234 } 235 236 if (ctx->op.encap.algctx == NULL) { 237 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 238 return -2; 239 } 240 241 if (out != NULL && secret == NULL) 242 return 0; 243 244 return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx, 245 out, outlen, secret, secretlen); 246 } 247 248 int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) 249 { 250 return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, NULL); 251 } 252 253 int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpub, 254 const OSSL_PARAM params[]) 255 { 256 if (authpub == NULL) 257 return 0; 258 return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, authpub); 259 } 260 261 int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, 262 unsigned char *secret, size_t *secretlen, 263 const unsigned char *in, size_t inlen) 264 { 265 if (ctx == NULL 266 || (in == NULL || inlen == 0) 267 || (secret == NULL && secretlen == NULL)) 268 return 0; 269 270 if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) { 271 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 272 return -1; 273 } 274 275 if (ctx->op.encap.algctx == NULL) { 276 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 277 return -2; 278 } 279 return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx, 280 secret, secretlen, in, inlen); 281 } 282 283 static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov) 284 { 285 EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM)); 286 287 if (kem == NULL) 288 return NULL; 289 290 if (!CRYPTO_NEW_REF(&kem->refcnt, 1) 291 || !ossl_provider_up_ref(prov)) { 292 CRYPTO_FREE_REF(&kem->refcnt); 293 OPENSSL_free(kem); 294 return NULL; 295 } 296 kem->prov = prov; 297 298 return kem; 299 } 300 301 static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, 302 OSSL_PROVIDER *prov) 303 { 304 const OSSL_DISPATCH *fns = algodef->implementation; 305 EVP_KEM *kem = NULL; 306 int ctxfncnt = 0, encfncnt = 0, decfncnt = 0; 307 int gparamfncnt = 0, sparamfncnt = 0; 308 309 if ((kem = evp_kem_new(prov)) == NULL) { 310 ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); 311 goto err; 312 } 313 314 kem->name_id = name_id; 315 if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) 316 goto err; 317 kem->description = algodef->algorithm_description; 318 319 for (; fns->function_id != 0; fns++) { 320 switch (fns->function_id) { 321 case OSSL_FUNC_KEM_NEWCTX: 322 if (kem->newctx != NULL) 323 break; 324 kem->newctx = OSSL_FUNC_kem_newctx(fns); 325 ctxfncnt++; 326 break; 327 case OSSL_FUNC_KEM_ENCAPSULATE_INIT: 328 if (kem->encapsulate_init != NULL) 329 break; 330 kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns); 331 encfncnt++; 332 break; 333 case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT: 334 if (kem->auth_encapsulate_init != NULL) 335 break; 336 kem->auth_encapsulate_init = OSSL_FUNC_kem_auth_encapsulate_init(fns); 337 encfncnt++; 338 break; 339 case OSSL_FUNC_KEM_ENCAPSULATE: 340 if (kem->encapsulate != NULL) 341 break; 342 kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns); 343 encfncnt++; 344 break; 345 case OSSL_FUNC_KEM_DECAPSULATE_INIT: 346 if (kem->decapsulate_init != NULL) 347 break; 348 kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns); 349 decfncnt++; 350 break; 351 case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT: 352 if (kem->auth_decapsulate_init != NULL) 353 break; 354 kem->auth_decapsulate_init = OSSL_FUNC_kem_auth_decapsulate_init(fns); 355 decfncnt++; 356 break; 357 case OSSL_FUNC_KEM_DECAPSULATE: 358 if (kem->decapsulate != NULL) 359 break; 360 kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns); 361 decfncnt++; 362 break; 363 case OSSL_FUNC_KEM_FREECTX: 364 if (kem->freectx != NULL) 365 break; 366 kem->freectx = OSSL_FUNC_kem_freectx(fns); 367 ctxfncnt++; 368 break; 369 case OSSL_FUNC_KEM_DUPCTX: 370 if (kem->dupctx != NULL) 371 break; 372 kem->dupctx = OSSL_FUNC_kem_dupctx(fns); 373 break; 374 case OSSL_FUNC_KEM_GET_CTX_PARAMS: 375 if (kem->get_ctx_params != NULL) 376 break; 377 kem->get_ctx_params 378 = OSSL_FUNC_kem_get_ctx_params(fns); 379 gparamfncnt++; 380 break; 381 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS: 382 if (kem->gettable_ctx_params != NULL) 383 break; 384 kem->gettable_ctx_params 385 = OSSL_FUNC_kem_gettable_ctx_params(fns); 386 gparamfncnt++; 387 break; 388 case OSSL_FUNC_KEM_SET_CTX_PARAMS: 389 if (kem->set_ctx_params != NULL) 390 break; 391 kem->set_ctx_params 392 = OSSL_FUNC_kem_set_ctx_params(fns); 393 sparamfncnt++; 394 break; 395 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS: 396 if (kem->settable_ctx_params != NULL) 397 break; 398 kem->settable_ctx_params 399 = OSSL_FUNC_kem_settable_ctx_params(fns); 400 sparamfncnt++; 401 break; 402 } 403 } 404 if (ctxfncnt != 2 405 || (encfncnt != 0 && encfncnt != 2 && encfncnt != 3) 406 || (decfncnt != 0 && decfncnt != 2 && decfncnt != 3) 407 || (encfncnt != decfncnt) 408 || (gparamfncnt != 0 && gparamfncnt != 2) 409 || (sparamfncnt != 0 && sparamfncnt != 2)) { 410 /* 411 * In order to be a consistent set of functions we must have at least 412 * a set of context functions (newctx and freectx) as well as a pair 413 * (or triplet) of "kem" functions: 414 * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or 415 * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate). 416 * set_ctx_params and settable_ctx_params are optional, but if one of 417 * them is present then the other one must also be present. The same 418 * applies to get_ctx_params and gettable_ctx_params. 419 * The dupctx function is optional. 420 */ 421 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); 422 goto err; 423 } 424 425 return kem; 426 err: 427 EVP_KEM_free(kem); 428 return NULL; 429 } 430 431 void EVP_KEM_free(EVP_KEM *kem) 432 { 433 int i; 434 435 if (kem == NULL) 436 return; 437 438 CRYPTO_DOWN_REF(&kem->refcnt, &i); 439 if (i > 0) 440 return; 441 OPENSSL_free(kem->type_name); 442 ossl_provider_free(kem->prov); 443 CRYPTO_FREE_REF(&kem->refcnt); 444 OPENSSL_free(kem); 445 } 446 447 int EVP_KEM_up_ref(EVP_KEM *kem) 448 { 449 int ref = 0; 450 451 CRYPTO_UP_REF(&kem->refcnt, &ref); 452 return 1; 453 } 454 455 OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem) 456 { 457 return kem->prov; 458 } 459 460 EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, 461 const char *properties) 462 { 463 return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties, 464 evp_kem_from_algorithm, 465 evp_kem_up_ref, 466 evp_kem_free); 467 } 468 469 EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm, 470 const char *properties) 471 { 472 return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties, 473 evp_kem_from_algorithm, 474 evp_kem_up_ref, 475 evp_kem_free); 476 } 477 478 int EVP_KEM_is_a(const EVP_KEM *kem, const char *name) 479 { 480 return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name); 481 } 482 483 int evp_kem_get_number(const EVP_KEM *kem) 484 { 485 return kem->name_id; 486 } 487 488 const char *EVP_KEM_get0_name(const EVP_KEM *kem) 489 { 490 return kem->type_name; 491 } 492 493 const char *EVP_KEM_get0_description(const EVP_KEM *kem) 494 { 495 return kem->description; 496 } 497 498 void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx, 499 void (*fn)(EVP_KEM *kem, void *arg), 500 void *arg) 501 { 502 evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg, 503 evp_kem_from_algorithm, 504 evp_kem_up_ref, 505 evp_kem_free); 506 } 507 508 int EVP_KEM_names_do_all(const EVP_KEM *kem, 509 void (*fn)(const char *name, void *data), 510 void *data) 511 { 512 if (kem->prov != NULL) 513 return evp_names_do_all(kem->prov, kem->name_id, fn, data); 514 515 return 1; 516 } 517 518 const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem) 519 { 520 void *provctx; 521 522 if (kem == NULL || kem->gettable_ctx_params == NULL) 523 return NULL; 524 525 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem)); 526 return kem->gettable_ctx_params(NULL, provctx); 527 } 528 529 const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem) 530 { 531 void *provctx; 532 533 if (kem == NULL || kem->settable_ctx_params == NULL) 534 return NULL; 535 536 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem)); 537 return kem->settable_ctx_params(NULL, provctx); 538 } 539