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