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 #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
evp_kem_free(void * data)20 static void evp_kem_free(void *data)
21 {
22 EVP_KEM_free(data);
23 }
24
evp_kem_up_ref(void * data)25 static int evp_kem_up_ref(void *data)
26 {
27 return EVP_KEM_up_ref(data);
28 }
29
evp_kem_init(EVP_PKEY_CTX * ctx,int operation,const OSSL_PARAM params[],EVP_PKEY * authkey)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 =
133 evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
134 EVP_KEYMGMT_get0_name(ctx->keymgmt),
135 ctx->propquery);
136 if (tmp_keymgmt != NULL) {
137 provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
138 &tmp_keymgmt, ctx->propquery);
139 if (provkey != NULL && authkey != NULL) {
140 provauthkey = evp_pkey_export_to_provider(authkey, ctx->libctx,
141 &tmp_keymgmt,
142 ctx->propquery);
143 if (provauthkey == NULL) {
144 EVP_KEM_free(kem);
145 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
146 goto err;
147 }
148 }
149 }
150 if (tmp_keymgmt == NULL)
151 EVP_KEYMGMT_free(tmp_keymgmt_tofree);
152 }
153
154 if (provkey == NULL) {
155 EVP_KEM_free(kem);
156 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
157 goto err;
158 }
159
160 ctx->op.encap.kem = kem;
161 ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
162 if (ctx->op.encap.algctx == NULL) {
163 /* The provider key can stay in the cache */
164 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
165 goto err;
166 }
167
168 switch (operation) {
169 case EVP_PKEY_OP_ENCAPSULATE:
170 if (provauthkey != NULL && kem->auth_encapsulate_init != NULL) {
171 ret = kem->auth_encapsulate_init(ctx->op.encap.algctx, provkey,
172 provauthkey, params);
173 } else if (provauthkey == NULL && kem->encapsulate_init != NULL) {
174 ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params);
175 } else {
176 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
177 ret = -2;
178 goto err;
179 }
180 break;
181 case EVP_PKEY_OP_DECAPSULATE:
182 if (provauthkey != NULL && kem->auth_decapsulate_init != NULL) {
183 ret = kem->auth_decapsulate_init(ctx->op.encap.algctx, provkey,
184 provauthkey, params);
185 } else if (provauthkey == NULL && kem->encapsulate_init != NULL) {
186 ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params);
187 } else {
188 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
189 ret = -2;
190 goto err;
191 }
192 break;
193 default:
194 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
195 goto err;
196 }
197
198 EVP_KEYMGMT_free(tmp_keymgmt);
199 tmp_keymgmt = NULL;
200
201 if (ret > 0)
202 return 1;
203 err:
204 if (ret <= 0) {
205 evp_pkey_ctx_free_old_ops(ctx);
206 ctx->operation = EVP_PKEY_OP_UNDEFINED;
207 }
208 EVP_KEYMGMT_free(tmp_keymgmt);
209 return ret;
210 }
211
EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX * ctx,EVP_PKEY * authpriv,const OSSL_PARAM params[])212 int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv,
213 const OSSL_PARAM params[])
214 {
215 if (authpriv == NULL)
216 return 0;
217 return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, authpriv);
218 }
219
EVP_PKEY_encapsulate_init(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])220 int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
221 {
222 return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, NULL);
223 }
224
EVP_PKEY_encapsulate(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,unsigned char * secret,size_t * secretlen)225 int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
226 unsigned char *out, size_t *outlen,
227 unsigned char *secret, size_t *secretlen)
228 {
229 if (ctx == NULL)
230 return 0;
231
232 if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) {
233 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
234 return -1;
235 }
236
237 if (ctx->op.encap.algctx == NULL) {
238 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
239 return -2;
240 }
241
242 if (out != NULL && secret == NULL)
243 return 0;
244
245 return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx,
246 out, outlen, secret, secretlen);
247 }
248
EVP_PKEY_decapsulate_init(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])249 int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
250 {
251 return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, NULL);
252 }
253
EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX * ctx,EVP_PKEY * authpub,const OSSL_PARAM params[])254 int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpub,
255 const OSSL_PARAM params[])
256 {
257 if (authpub == NULL)
258 return 0;
259 return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, authpub);
260 }
261
EVP_PKEY_decapsulate(EVP_PKEY_CTX * ctx,unsigned char * secret,size_t * secretlen,const unsigned char * in,size_t inlen)262 int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
263 unsigned char *secret, size_t *secretlen,
264 const unsigned char *in, size_t inlen)
265 {
266 if (ctx == NULL
267 || (in == NULL || inlen == 0)
268 || (secret == NULL && secretlen == NULL))
269 return 0;
270
271 if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) {
272 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
273 return -1;
274 }
275
276 if (ctx->op.encap.algctx == NULL) {
277 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
278 return -2;
279 }
280 return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx,
281 secret, secretlen, in, inlen);
282 }
283
evp_kem_new(OSSL_PROVIDER * prov)284 static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov)
285 {
286 EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM));
287
288 if (kem == NULL)
289 return NULL;
290
291 if (!CRYPTO_NEW_REF(&kem->refcnt, 1)
292 || !ossl_provider_up_ref(prov)) {
293 CRYPTO_FREE_REF(&kem->refcnt);
294 OPENSSL_free(kem);
295 return NULL;
296 }
297 kem->prov = prov;
298
299 return kem;
300 }
301
evp_kem_from_algorithm(int name_id,const OSSL_ALGORITHM * algodef,OSSL_PROVIDER * prov)302 static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
303 OSSL_PROVIDER *prov)
304 {
305 const OSSL_DISPATCH *fns = algodef->implementation;
306 EVP_KEM *kem = NULL;
307 int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
308 int gparamfncnt = 0, sparamfncnt = 0;
309
310 if ((kem = evp_kem_new(prov)) == NULL) {
311 ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
312 goto err;
313 }
314
315 kem->name_id = name_id;
316 if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
317 goto err;
318 kem->description = algodef->algorithm_description;
319
320 for (; fns->function_id != 0; fns++) {
321 switch (fns->function_id) {
322 case OSSL_FUNC_KEM_NEWCTX:
323 if (kem->newctx != NULL)
324 break;
325 kem->newctx = OSSL_FUNC_kem_newctx(fns);
326 ctxfncnt++;
327 break;
328 case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
329 if (kem->encapsulate_init != NULL)
330 break;
331 kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
332 encfncnt++;
333 break;
334 case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT:
335 if (kem->auth_encapsulate_init != NULL)
336 break;
337 kem->auth_encapsulate_init = OSSL_FUNC_kem_auth_encapsulate_init(fns);
338 encfncnt++;
339 break;
340 case OSSL_FUNC_KEM_ENCAPSULATE:
341 if (kem->encapsulate != NULL)
342 break;
343 kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
344 encfncnt++;
345 break;
346 case OSSL_FUNC_KEM_DECAPSULATE_INIT:
347 if (kem->decapsulate_init != NULL)
348 break;
349 kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
350 decfncnt++;
351 break;
352 case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT:
353 if (kem->auth_decapsulate_init != NULL)
354 break;
355 kem->auth_decapsulate_init = OSSL_FUNC_kem_auth_decapsulate_init(fns);
356 decfncnt++;
357 break;
358 case OSSL_FUNC_KEM_DECAPSULATE:
359 if (kem->decapsulate != NULL)
360 break;
361 kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
362 decfncnt++;
363 break;
364 case OSSL_FUNC_KEM_FREECTX:
365 if (kem->freectx != NULL)
366 break;
367 kem->freectx = OSSL_FUNC_kem_freectx(fns);
368 ctxfncnt++;
369 break;
370 case OSSL_FUNC_KEM_DUPCTX:
371 if (kem->dupctx != NULL)
372 break;
373 kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
374 break;
375 case OSSL_FUNC_KEM_GET_CTX_PARAMS:
376 if (kem->get_ctx_params != NULL)
377 break;
378 kem->get_ctx_params
379 = OSSL_FUNC_kem_get_ctx_params(fns);
380 gparamfncnt++;
381 break;
382 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
383 if (kem->gettable_ctx_params != NULL)
384 break;
385 kem->gettable_ctx_params
386 = OSSL_FUNC_kem_gettable_ctx_params(fns);
387 gparamfncnt++;
388 break;
389 case OSSL_FUNC_KEM_SET_CTX_PARAMS:
390 if (kem->set_ctx_params != NULL)
391 break;
392 kem->set_ctx_params
393 = OSSL_FUNC_kem_set_ctx_params(fns);
394 sparamfncnt++;
395 break;
396 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
397 if (kem->settable_ctx_params != NULL)
398 break;
399 kem->settable_ctx_params
400 = OSSL_FUNC_kem_settable_ctx_params(fns);
401 sparamfncnt++;
402 break;
403 }
404 }
405 if (ctxfncnt != 2
406 || (encfncnt != 0 && encfncnt != 2 && encfncnt != 3)
407 || (decfncnt != 0 && decfncnt != 2 && decfncnt != 3)
408 || (encfncnt != decfncnt)
409 || (gparamfncnt != 0 && gparamfncnt != 2)
410 || (sparamfncnt != 0 && sparamfncnt != 2)) {
411 /*
412 * In order to be a consistent set of functions we must have at least
413 * a set of context functions (newctx and freectx) as well as a pair
414 * (or triplet) of "kem" functions:
415 * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or
416 * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate).
417 * set_ctx_params and settable_ctx_params are optional, but if one of
418 * them is present then the other one must also be present. The same
419 * applies to get_ctx_params and gettable_ctx_params.
420 * The dupctx function is optional.
421 */
422 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
423 goto err;
424 }
425
426 return kem;
427 err:
428 EVP_KEM_free(kem);
429 return NULL;
430 }
431
EVP_KEM_free(EVP_KEM * kem)432 void EVP_KEM_free(EVP_KEM *kem)
433 {
434 int i;
435
436 if (kem == NULL)
437 return;
438
439 CRYPTO_DOWN_REF(&kem->refcnt, &i);
440 if (i > 0)
441 return;
442 OPENSSL_free(kem->type_name);
443 ossl_provider_free(kem->prov);
444 CRYPTO_FREE_REF(&kem->refcnt);
445 OPENSSL_free(kem);
446 }
447
EVP_KEM_up_ref(EVP_KEM * kem)448 int EVP_KEM_up_ref(EVP_KEM *kem)
449 {
450 int ref = 0;
451
452 CRYPTO_UP_REF(&kem->refcnt, &ref);
453 return 1;
454 }
455
EVP_KEM_get0_provider(const EVP_KEM * kem)456 OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
457 {
458 return kem->prov;
459 }
460
EVP_KEM_fetch(OSSL_LIB_CTX * ctx,const char * algorithm,const char * properties)461 EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
462 const char *properties)
463 {
464 return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
465 evp_kem_from_algorithm,
466 evp_kem_up_ref,
467 evp_kem_free);
468 }
469
evp_kem_fetch_from_prov(OSSL_PROVIDER * prov,const char * algorithm,const char * properties)470 EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
471 const char *properties)
472 {
473 return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
474 evp_kem_from_algorithm,
475 evp_kem_up_ref,
476 evp_kem_free);
477 }
478
EVP_KEM_is_a(const EVP_KEM * kem,const char * name)479 int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
480 {
481 return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name);
482 }
483
evp_kem_get_number(const EVP_KEM * kem)484 int evp_kem_get_number(const EVP_KEM *kem)
485 {
486 return kem->name_id;
487 }
488
EVP_KEM_get0_name(const EVP_KEM * kem)489 const char *EVP_KEM_get0_name(const EVP_KEM *kem)
490 {
491 return kem->type_name;
492 }
493
EVP_KEM_get0_description(const EVP_KEM * kem)494 const char *EVP_KEM_get0_description(const EVP_KEM *kem)
495 {
496 return kem->description;
497 }
498
EVP_KEM_do_all_provided(OSSL_LIB_CTX * libctx,void (* fn)(EVP_KEM * kem,void * arg),void * arg)499 void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
500 void (*fn)(EVP_KEM *kem, void *arg),
501 void *arg)
502 {
503 evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
504 evp_kem_from_algorithm,
505 evp_kem_up_ref,
506 evp_kem_free);
507 }
508
EVP_KEM_names_do_all(const EVP_KEM * kem,void (* fn)(const char * name,void * data),void * data)509 int EVP_KEM_names_do_all(const EVP_KEM *kem,
510 void (*fn)(const char *name, void *data),
511 void *data)
512 {
513 if (kem->prov != NULL)
514 return evp_names_do_all(kem->prov, kem->name_id, fn, data);
515
516 return 1;
517 }
518
EVP_KEM_gettable_ctx_params(const EVP_KEM * kem)519 const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
520 {
521 void *provctx;
522
523 if (kem == NULL || kem->gettable_ctx_params == NULL)
524 return NULL;
525
526 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
527 return kem->gettable_ctx_params(NULL, provctx);
528 }
529
EVP_KEM_settable_ctx_params(const EVP_KEM * kem)530 const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
531 {
532 void *provctx;
533
534 if (kem == NULL || kem->settable_ctx_params == NULL)
535 return NULL;
536
537 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
538 return kem->settable_ctx_params(NULL, provctx);
539 }
540