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