xref: /freebsd-src/crypto/openssl/crypto/evp/evp_fetch.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #include <stddef.h>
11*b077aed3SPierre Pronchery #include <openssl/types.h>
12*b077aed3SPierre Pronchery #include <openssl/evp.h>
13*b077aed3SPierre Pronchery #include <openssl/core.h>
14*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
15*b077aed3SPierre Pronchery #include "internal/thread_once.h"
16*b077aed3SPierre Pronchery #include "internal/property.h"
17*b077aed3SPierre Pronchery #include "internal/core.h"
18*b077aed3SPierre Pronchery #include "internal/provider.h"
19*b077aed3SPierre Pronchery #include "internal/namemap.h"
20*b077aed3SPierre Pronchery #include "internal/property.h"
21*b077aed3SPierre Pronchery #include "crypto/evp.h"    /* evp_local.h needs it */
22*b077aed3SPierre Pronchery #include "evp_local.h"
23*b077aed3SPierre Pronchery 
24*b077aed3SPierre Pronchery #define NAME_SEPARATOR ':'
25*b077aed3SPierre Pronchery 
26*b077aed3SPierre Pronchery static void evp_method_store_free(void *vstore)
27*b077aed3SPierre Pronchery {
28*b077aed3SPierre Pronchery     ossl_method_store_free(vstore);
29*b077aed3SPierre Pronchery }
30*b077aed3SPierre Pronchery 
31*b077aed3SPierre Pronchery static void *evp_method_store_new(OSSL_LIB_CTX *ctx)
32*b077aed3SPierre Pronchery {
33*b077aed3SPierre Pronchery     return ossl_method_store_new(ctx);
34*b077aed3SPierre Pronchery }
35*b077aed3SPierre Pronchery 
36*b077aed3SPierre Pronchery 
37*b077aed3SPierre Pronchery static const OSSL_LIB_CTX_METHOD evp_method_store_method = {
38*b077aed3SPierre Pronchery     /* We want evp_method_store to be cleaned up before the provider store */
39*b077aed3SPierre Pronchery     OSSL_LIB_CTX_METHOD_PRIORITY_2,
40*b077aed3SPierre Pronchery     evp_method_store_new,
41*b077aed3SPierre Pronchery     evp_method_store_free,
42*b077aed3SPierre Pronchery };
43*b077aed3SPierre Pronchery 
44*b077aed3SPierre Pronchery /* Data to be passed through ossl_method_construct() */
45*b077aed3SPierre Pronchery struct evp_method_data_st {
46*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
47*b077aed3SPierre Pronchery     int operation_id;            /* For get_evp_method_from_store() */
48*b077aed3SPierre Pronchery     int name_id;                 /* For get_evp_method_from_store() */
49*b077aed3SPierre Pronchery     const char *names;           /* For get_evp_method_from_store() */
50*b077aed3SPierre Pronchery     const char *propquery;       /* For get_evp_method_from_store() */
51*b077aed3SPierre Pronchery 
52*b077aed3SPierre Pronchery     OSSL_METHOD_STORE *tmp_store; /* For get_tmp_evp_method_store() */
53*b077aed3SPierre Pronchery 
54*b077aed3SPierre Pronchery     unsigned int flag_construct_error_occurred : 1;
55*b077aed3SPierre Pronchery 
56*b077aed3SPierre Pronchery     void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *,
57*b077aed3SPierre Pronchery                                    OSSL_PROVIDER *);
58*b077aed3SPierre Pronchery     int (*refcnt_up_method)(void *method);
59*b077aed3SPierre Pronchery     void (*destruct_method)(void *method);
60*b077aed3SPierre Pronchery };
61*b077aed3SPierre Pronchery 
62*b077aed3SPierre Pronchery /*
63*b077aed3SPierre Pronchery  * Generic routines to fetch / create EVP methods with ossl_method_construct()
64*b077aed3SPierre Pronchery  */
65*b077aed3SPierre Pronchery static void *get_tmp_evp_method_store(void *data)
66*b077aed3SPierre Pronchery {
67*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
68*b077aed3SPierre Pronchery 
69*b077aed3SPierre Pronchery     if (methdata->tmp_store == NULL)
70*b077aed3SPierre Pronchery         methdata->tmp_store = ossl_method_store_new(methdata->libctx);
71*b077aed3SPierre Pronchery     return methdata->tmp_store;
72*b077aed3SPierre Pronchery }
73*b077aed3SPierre Pronchery 
74*b077aed3SPierre Pronchery  static void dealloc_tmp_evp_method_store(void *store)
75*b077aed3SPierre Pronchery {
76*b077aed3SPierre Pronchery     if (store != NULL)
77*b077aed3SPierre Pronchery         ossl_method_store_free(store);
78*b077aed3SPierre Pronchery }
79*b077aed3SPierre Pronchery 
80*b077aed3SPierre Pronchery static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx)
81*b077aed3SPierre Pronchery {
82*b077aed3SPierre Pronchery     return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX,
83*b077aed3SPierre Pronchery                                  &evp_method_store_method);
84*b077aed3SPierre Pronchery }
85*b077aed3SPierre Pronchery 
86*b077aed3SPierre Pronchery static int reserve_evp_method_store(void *store, void *data)
87*b077aed3SPierre Pronchery {
88*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
89*b077aed3SPierre Pronchery 
90*b077aed3SPierre Pronchery     if (store == NULL
91*b077aed3SPierre Pronchery         && (store = get_evp_method_store(methdata->libctx)) == NULL)
92*b077aed3SPierre Pronchery         return 0;
93*b077aed3SPierre Pronchery 
94*b077aed3SPierre Pronchery     return ossl_method_lock_store(store);
95*b077aed3SPierre Pronchery }
96*b077aed3SPierre Pronchery 
97*b077aed3SPierre Pronchery static int unreserve_evp_method_store(void *store, void *data)
98*b077aed3SPierre Pronchery {
99*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
100*b077aed3SPierre Pronchery 
101*b077aed3SPierre Pronchery     if (store == NULL
102*b077aed3SPierre Pronchery         && (store = get_evp_method_store(methdata->libctx)) == NULL)
103*b077aed3SPierre Pronchery         return 0;
104*b077aed3SPierre Pronchery 
105*b077aed3SPierre Pronchery     return ossl_method_unlock_store(store);
106*b077aed3SPierre Pronchery }
107*b077aed3SPierre Pronchery 
108*b077aed3SPierre Pronchery /*
109*b077aed3SPierre Pronchery  * To identify the method in the EVP method store, we mix the name identity
110*b077aed3SPierre Pronchery  * with the operation identity, under the assumption that we don't have more
111*b077aed3SPierre Pronchery  * than 2^23 names or more than 2^8 operation types.
112*b077aed3SPierre Pronchery  *
113*b077aed3SPierre Pronchery  * The resulting identity is a 31-bit integer, composed like this:
114*b077aed3SPierre Pronchery  *
115*b077aed3SPierre Pronchery  * +---------23 bits--------+-8 bits-+
116*b077aed3SPierre Pronchery  * |      name identity     | op id  |
117*b077aed3SPierre Pronchery  * +------------------------+--------+
118*b077aed3SPierre Pronchery  *
119*b077aed3SPierre Pronchery  * We limit this composite number to 31 bits, thus leaving the top uint32_t
120*b077aed3SPierre Pronchery  * bit always zero, to avoid negative sign extension when downshifting after
121*b077aed3SPierre Pronchery  * this number happens to be passed to an int (which happens as soon as it's
122*b077aed3SPierre Pronchery  * passed to ossl_method_store_cache_set(), and it's in that form that it
123*b077aed3SPierre Pronchery  * gets passed along to filter_on_operation_id(), defined further down.
124*b077aed3SPierre Pronchery  */
125*b077aed3SPierre Pronchery #define METHOD_ID_OPERATION_MASK        0x000000FF
126*b077aed3SPierre Pronchery #define METHOD_ID_OPERATION_MAX         ((1 << 8) - 1)
127*b077aed3SPierre Pronchery #define METHOD_ID_NAME_MASK             0x7FFFFF00
128*b077aed3SPierre Pronchery #define METHOD_ID_NAME_OFFSET           8
129*b077aed3SPierre Pronchery #define METHOD_ID_NAME_MAX              ((1 << 23) - 1)
130*b077aed3SPierre Pronchery static uint32_t evp_method_id(int name_id, unsigned int operation_id)
131*b077aed3SPierre Pronchery {
132*b077aed3SPierre Pronchery     if (!ossl_assert(name_id > 0 && name_id <= METHOD_ID_NAME_MAX)
133*b077aed3SPierre Pronchery         || !ossl_assert(operation_id > 0
134*b077aed3SPierre Pronchery                         && operation_id <= METHOD_ID_OPERATION_MAX))
135*b077aed3SPierre Pronchery         return 0;
136*b077aed3SPierre Pronchery     return (((name_id << METHOD_ID_NAME_OFFSET) & METHOD_ID_NAME_MASK)
137*b077aed3SPierre Pronchery             | (operation_id & METHOD_ID_OPERATION_MASK));
138*b077aed3SPierre Pronchery }
139*b077aed3SPierre Pronchery 
140*b077aed3SPierre Pronchery static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov,
141*b077aed3SPierre Pronchery                                        void *data)
142*b077aed3SPierre Pronchery {
143*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
144*b077aed3SPierre Pronchery     void *method = NULL;
145*b077aed3SPierre Pronchery     int name_id = 0;
146*b077aed3SPierre Pronchery     uint32_t meth_id;
147*b077aed3SPierre Pronchery 
148*b077aed3SPierre Pronchery     /*
149*b077aed3SPierre Pronchery      * get_evp_method_from_store() is only called to try and get the method
150*b077aed3SPierre Pronchery      * that evp_generic_fetch() is asking for, and the operation id as well
151*b077aed3SPierre Pronchery      * as the name or name id are passed via methdata.
152*b077aed3SPierre Pronchery      */
153*b077aed3SPierre Pronchery     if ((name_id = methdata->name_id) == 0 && methdata->names != NULL) {
154*b077aed3SPierre Pronchery         OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
155*b077aed3SPierre Pronchery         const char *names = methdata->names;
156*b077aed3SPierre Pronchery         const char *q = strchr(names, NAME_SEPARATOR);
157*b077aed3SPierre Pronchery         size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
158*b077aed3SPierre Pronchery 
159*b077aed3SPierre Pronchery         if (namemap == 0)
160*b077aed3SPierre Pronchery             return NULL;
161*b077aed3SPierre Pronchery         name_id = ossl_namemap_name2num_n(namemap, names, l);
162*b077aed3SPierre Pronchery     }
163*b077aed3SPierre Pronchery 
164*b077aed3SPierre Pronchery     if (name_id == 0
165*b077aed3SPierre Pronchery         || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
166*b077aed3SPierre Pronchery         return NULL;
167*b077aed3SPierre Pronchery 
168*b077aed3SPierre Pronchery     if (store == NULL
169*b077aed3SPierre Pronchery         && (store = get_evp_method_store(methdata->libctx)) == NULL)
170*b077aed3SPierre Pronchery         return NULL;
171*b077aed3SPierre Pronchery 
172*b077aed3SPierre Pronchery     if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, prov,
173*b077aed3SPierre Pronchery                                  &method))
174*b077aed3SPierre Pronchery         return NULL;
175*b077aed3SPierre Pronchery     return method;
176*b077aed3SPierre Pronchery }
177*b077aed3SPierre Pronchery 
178*b077aed3SPierre Pronchery static int put_evp_method_in_store(void *store, void *method,
179*b077aed3SPierre Pronchery                                    const OSSL_PROVIDER *prov,
180*b077aed3SPierre Pronchery                                    const char *names, const char *propdef,
181*b077aed3SPierre Pronchery                                    void *data)
182*b077aed3SPierre Pronchery {
183*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
184*b077aed3SPierre Pronchery     OSSL_NAMEMAP *namemap;
185*b077aed3SPierre Pronchery     int name_id;
186*b077aed3SPierre Pronchery     uint32_t meth_id;
187*b077aed3SPierre Pronchery     size_t l = 0;
188*b077aed3SPierre Pronchery 
189*b077aed3SPierre Pronchery     /*
190*b077aed3SPierre Pronchery      * put_evp_method_in_store() is only called with an EVP method that was
191*b077aed3SPierre Pronchery      * successfully created by construct_method() below, which means that
192*b077aed3SPierre Pronchery      * all the names should already be stored in the namemap with the same
193*b077aed3SPierre Pronchery      * numeric identity, so just use the first to get that identity.
194*b077aed3SPierre Pronchery      */
195*b077aed3SPierre Pronchery     if (names != NULL) {
196*b077aed3SPierre Pronchery         const char *q = strchr(names, NAME_SEPARATOR);
197*b077aed3SPierre Pronchery 
198*b077aed3SPierre Pronchery         l = (q == NULL ? strlen(names) : (size_t)(q - names));
199*b077aed3SPierre Pronchery     }
200*b077aed3SPierre Pronchery 
201*b077aed3SPierre Pronchery     if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
202*b077aed3SPierre Pronchery         || (name_id = ossl_namemap_name2num_n(namemap, names, l)) == 0
203*b077aed3SPierre Pronchery         || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
204*b077aed3SPierre Pronchery         return 0;
205*b077aed3SPierre Pronchery 
206*b077aed3SPierre Pronchery     if (store == NULL
207*b077aed3SPierre Pronchery         && (store = get_evp_method_store(methdata->libctx)) == NULL)
208*b077aed3SPierre Pronchery         return 0;
209*b077aed3SPierre Pronchery 
210*b077aed3SPierre Pronchery     return ossl_method_store_add(store, prov, meth_id, propdef, method,
211*b077aed3SPierre Pronchery                                  methdata->refcnt_up_method,
212*b077aed3SPierre Pronchery                                  methdata->destruct_method);
213*b077aed3SPierre Pronchery }
214*b077aed3SPierre Pronchery 
215*b077aed3SPierre Pronchery /*
216*b077aed3SPierre Pronchery  * The core fetching functionality passes the name of the implementation.
217*b077aed3SPierre Pronchery  * This function is responsible to getting an identity number for it.
218*b077aed3SPierre Pronchery  */
219*b077aed3SPierre Pronchery static void *construct_evp_method(const OSSL_ALGORITHM *algodef,
220*b077aed3SPierre Pronchery                                   OSSL_PROVIDER *prov, void *data)
221*b077aed3SPierre Pronchery {
222*b077aed3SPierre Pronchery     /*
223*b077aed3SPierre Pronchery      * This function is only called if get_evp_method_from_store() returned
224*b077aed3SPierre Pronchery      * NULL, so it's safe to say that of all the spots to create a new
225*b077aed3SPierre Pronchery      * namemap entry, this is it.  Should the name already exist there, we
226*b077aed3SPierre Pronchery      * know that ossl_namemap_add_name() will return its corresponding
227*b077aed3SPierre Pronchery      * number.
228*b077aed3SPierre Pronchery      */
229*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
230*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
231*b077aed3SPierre Pronchery     OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
232*b077aed3SPierre Pronchery     const char *names = algodef->algorithm_names;
233*b077aed3SPierre Pronchery     int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
234*b077aed3SPierre Pronchery     void *method;
235*b077aed3SPierre Pronchery 
236*b077aed3SPierre Pronchery     if (name_id == 0)
237*b077aed3SPierre Pronchery         return NULL;
238*b077aed3SPierre Pronchery 
239*b077aed3SPierre Pronchery     method = methdata->method_from_algorithm(name_id, algodef, prov);
240*b077aed3SPierre Pronchery 
241*b077aed3SPierre Pronchery     /*
242*b077aed3SPierre Pronchery      * Flag to indicate that there was actual construction errors.  This
243*b077aed3SPierre Pronchery      * helps inner_evp_generic_fetch() determine what error it should
244*b077aed3SPierre Pronchery      * record on inaccessible algorithms.
245*b077aed3SPierre Pronchery      */
246*b077aed3SPierre Pronchery     if (method == NULL)
247*b077aed3SPierre Pronchery         methdata->flag_construct_error_occurred = 1;
248*b077aed3SPierre Pronchery 
249*b077aed3SPierre Pronchery     return method;
250*b077aed3SPierre Pronchery }
251*b077aed3SPierre Pronchery 
252*b077aed3SPierre Pronchery static void destruct_evp_method(void *method, void *data)
253*b077aed3SPierre Pronchery {
254*b077aed3SPierre Pronchery     struct evp_method_data_st *methdata = data;
255*b077aed3SPierre Pronchery 
256*b077aed3SPierre Pronchery     methdata->destruct_method(method);
257*b077aed3SPierre Pronchery }
258*b077aed3SPierre Pronchery 
259*b077aed3SPierre Pronchery static void *
260*b077aed3SPierre Pronchery inner_evp_generic_fetch(struct evp_method_data_st *methdata,
261*b077aed3SPierre Pronchery                         OSSL_PROVIDER *prov, int operation_id,
262*b077aed3SPierre Pronchery                         int name_id, const char *name,
263*b077aed3SPierre Pronchery                         const char *properties,
264*b077aed3SPierre Pronchery                         void *(*new_method)(int name_id,
265*b077aed3SPierre Pronchery                                             const OSSL_ALGORITHM *algodef,
266*b077aed3SPierre Pronchery                                             OSSL_PROVIDER *prov),
267*b077aed3SPierre Pronchery                         int (*up_ref_method)(void *),
268*b077aed3SPierre Pronchery                         void (*free_method)(void *))
269*b077aed3SPierre Pronchery {
270*b077aed3SPierre Pronchery     OSSL_METHOD_STORE *store = get_evp_method_store(methdata->libctx);
271*b077aed3SPierre Pronchery     OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
272*b077aed3SPierre Pronchery     const char *const propq = properties != NULL ? properties : "";
273*b077aed3SPierre Pronchery     uint32_t meth_id = 0;
274*b077aed3SPierre Pronchery     void *method = NULL;
275*b077aed3SPierre Pronchery     int unsupported = 0;
276*b077aed3SPierre Pronchery 
277*b077aed3SPierre Pronchery     if (store == NULL || namemap == NULL) {
278*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
279*b077aed3SPierre Pronchery         return NULL;
280*b077aed3SPierre Pronchery     }
281*b077aed3SPierre Pronchery 
282*b077aed3SPierre Pronchery     /*
283*b077aed3SPierre Pronchery      * If there's ever an operation_id == 0 passed, we have an internal
284*b077aed3SPierre Pronchery      * programming error.
285*b077aed3SPierre Pronchery      */
286*b077aed3SPierre Pronchery     if (!ossl_assert(operation_id > 0)) {
287*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
288*b077aed3SPierre Pronchery         return NULL;
289*b077aed3SPierre Pronchery     }
290*b077aed3SPierre Pronchery 
291*b077aed3SPierre Pronchery     /*
292*b077aed3SPierre Pronchery      * If we have been passed both a name_id and a name, we have an
293*b077aed3SPierre Pronchery      * internal programming error.
294*b077aed3SPierre Pronchery      */
295*b077aed3SPierre Pronchery     if (!ossl_assert(name_id == 0 || name == NULL)) {
296*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
297*b077aed3SPierre Pronchery         return NULL;
298*b077aed3SPierre Pronchery     }
299*b077aed3SPierre Pronchery 
300*b077aed3SPierre Pronchery     /* If we haven't received a name id yet, try to get one for the name */
301*b077aed3SPierre Pronchery     if (name_id == 0 && name != NULL)
302*b077aed3SPierre Pronchery         name_id = ossl_namemap_name2num(namemap, name);
303*b077aed3SPierre Pronchery 
304*b077aed3SPierre Pronchery     /*
305*b077aed3SPierre Pronchery      * If we have a name id, calculate a method id with evp_method_id().
306*b077aed3SPierre Pronchery      *
307*b077aed3SPierre Pronchery      * evp_method_id returns 0 if we have too many operations (more than
308*b077aed3SPierre Pronchery      * about 2^8) or too many names (more than about 2^24).  In that case,
309*b077aed3SPierre Pronchery      * we can't create any new method.
310*b077aed3SPierre Pronchery      * For all intents and purposes, this is an internal error.
311*b077aed3SPierre Pronchery      */
312*b077aed3SPierre Pronchery     if (name_id != 0 && (meth_id = evp_method_id(name_id, operation_id)) == 0) {
313*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
314*b077aed3SPierre Pronchery         return NULL;
315*b077aed3SPierre Pronchery     }
316*b077aed3SPierre Pronchery 
317*b077aed3SPierre Pronchery     /*
318*b077aed3SPierre Pronchery      * If we haven't found the name yet, chances are that the algorithm to
319*b077aed3SPierre Pronchery      * be fetched is unsupported.
320*b077aed3SPierre Pronchery      */
321*b077aed3SPierre Pronchery     if (name_id == 0)
322*b077aed3SPierre Pronchery         unsupported = 1;
323*b077aed3SPierre Pronchery 
324*b077aed3SPierre Pronchery     if (meth_id == 0
325*b077aed3SPierre Pronchery         || !ossl_method_store_cache_get(store, prov, meth_id, propq, &method)) {
326*b077aed3SPierre Pronchery         OSSL_METHOD_CONSTRUCT_METHOD mcm = {
327*b077aed3SPierre Pronchery             get_tmp_evp_method_store,
328*b077aed3SPierre Pronchery             reserve_evp_method_store,
329*b077aed3SPierre Pronchery             unreserve_evp_method_store,
330*b077aed3SPierre Pronchery             get_evp_method_from_store,
331*b077aed3SPierre Pronchery             put_evp_method_in_store,
332*b077aed3SPierre Pronchery             construct_evp_method,
333*b077aed3SPierre Pronchery             destruct_evp_method
334*b077aed3SPierre Pronchery         };
335*b077aed3SPierre Pronchery 
336*b077aed3SPierre Pronchery         methdata->operation_id = operation_id;
337*b077aed3SPierre Pronchery         methdata->name_id = name_id;
338*b077aed3SPierre Pronchery         methdata->names = name;
339*b077aed3SPierre Pronchery         methdata->propquery = propq;
340*b077aed3SPierre Pronchery         methdata->method_from_algorithm = new_method;
341*b077aed3SPierre Pronchery         methdata->refcnt_up_method = up_ref_method;
342*b077aed3SPierre Pronchery         methdata->destruct_method = free_method;
343*b077aed3SPierre Pronchery         methdata->flag_construct_error_occurred = 0;
344*b077aed3SPierre Pronchery         if ((method = ossl_method_construct(methdata->libctx, operation_id,
345*b077aed3SPierre Pronchery                                             &prov, 0 /* !force_cache */,
346*b077aed3SPierre Pronchery                                             &mcm, methdata)) != NULL) {
347*b077aed3SPierre Pronchery             /*
348*b077aed3SPierre Pronchery              * If construction did create a method for us, we know that
349*b077aed3SPierre Pronchery              * there is a correct name_id and meth_id, since those have
350*b077aed3SPierre Pronchery              * already been calculated in get_evp_method_from_store() and
351*b077aed3SPierre Pronchery              * put_evp_method_in_store() above.
352*b077aed3SPierre Pronchery              */
353*b077aed3SPierre Pronchery             if (name_id == 0)
354*b077aed3SPierre Pronchery                 name_id = ossl_namemap_name2num(namemap, name);
355*b077aed3SPierre Pronchery             meth_id = evp_method_id(name_id, operation_id);
356*b077aed3SPierre Pronchery             if (name_id != 0)
357*b077aed3SPierre Pronchery                 ossl_method_store_cache_set(store, prov, meth_id, propq,
358*b077aed3SPierre Pronchery                                             method, up_ref_method, free_method);
359*b077aed3SPierre Pronchery         }
360*b077aed3SPierre Pronchery 
361*b077aed3SPierre Pronchery         /*
362*b077aed3SPierre Pronchery          * If we never were in the constructor, the algorithm to be fetched
363*b077aed3SPierre Pronchery          * is unsupported.
364*b077aed3SPierre Pronchery          */
365*b077aed3SPierre Pronchery         unsupported = !methdata->flag_construct_error_occurred;
366*b077aed3SPierre Pronchery     }
367*b077aed3SPierre Pronchery 
368*b077aed3SPierre Pronchery     if ((name_id != 0 || name != NULL) && method == NULL) {
369*b077aed3SPierre Pronchery         int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
370*b077aed3SPierre Pronchery 
371*b077aed3SPierre Pronchery         if (name == NULL)
372*b077aed3SPierre Pronchery             name = ossl_namemap_num2name(namemap, name_id, 0);
373*b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_EVP, code,
374*b077aed3SPierre Pronchery                        "%s, Algorithm (%s : %d), Properties (%s)",
375*b077aed3SPierre Pronchery                        ossl_lib_ctx_get_descriptor(methdata->libctx),
376*b077aed3SPierre Pronchery                        name == NULL ? "<null>" : name, name_id,
377*b077aed3SPierre Pronchery                        properties == NULL ? "<null>" : properties);
378*b077aed3SPierre Pronchery     }
379*b077aed3SPierre Pronchery 
380*b077aed3SPierre Pronchery     return method;
381*b077aed3SPierre Pronchery }
382*b077aed3SPierre Pronchery 
383*b077aed3SPierre Pronchery void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
384*b077aed3SPierre Pronchery                         const char *name, const char *properties,
385*b077aed3SPierre Pronchery                         void *(*new_method)(int name_id,
386*b077aed3SPierre Pronchery                                             const OSSL_ALGORITHM *algodef,
387*b077aed3SPierre Pronchery                                             OSSL_PROVIDER *prov),
388*b077aed3SPierre Pronchery                         int (*up_ref_method)(void *),
389*b077aed3SPierre Pronchery                         void (*free_method)(void *))
390*b077aed3SPierre Pronchery {
391*b077aed3SPierre Pronchery     struct evp_method_data_st methdata;
392*b077aed3SPierre Pronchery     void *method;
393*b077aed3SPierre Pronchery 
394*b077aed3SPierre Pronchery     methdata.libctx = libctx;
395*b077aed3SPierre Pronchery     methdata.tmp_store = NULL;
396*b077aed3SPierre Pronchery     method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
397*b077aed3SPierre Pronchery                                      0, name, properties,
398*b077aed3SPierre Pronchery                                      new_method, up_ref_method, free_method);
399*b077aed3SPierre Pronchery     dealloc_tmp_evp_method_store(methdata.tmp_store);
400*b077aed3SPierre Pronchery     return method;
401*b077aed3SPierre Pronchery }
402*b077aed3SPierre Pronchery 
403*b077aed3SPierre Pronchery /*
404*b077aed3SPierre Pronchery  * evp_generic_fetch_by_number() is special, and only returns methods for
405*b077aed3SPierre Pronchery  * already known names, i.e. it refuses to work if no name_id can be found
406*b077aed3SPierre Pronchery  * (it's considered an internal programming error).
407*b077aed3SPierre Pronchery  * This is meant to be used when one method needs to fetch an associated
408*b077aed3SPierre Pronchery  * method.
409*b077aed3SPierre Pronchery  */
410*b077aed3SPierre Pronchery void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id,
411*b077aed3SPierre Pronchery                                   int name_id, const char *properties,
412*b077aed3SPierre Pronchery                                   void *(*new_method)(int name_id,
413*b077aed3SPierre Pronchery                                                       const OSSL_ALGORITHM *algodef,
414*b077aed3SPierre Pronchery                                                       OSSL_PROVIDER *prov),
415*b077aed3SPierre Pronchery                                   int (*up_ref_method)(void *),
416*b077aed3SPierre Pronchery                                   void (*free_method)(void *))
417*b077aed3SPierre Pronchery {
418*b077aed3SPierre Pronchery     struct evp_method_data_st methdata;
419*b077aed3SPierre Pronchery     void *method;
420*b077aed3SPierre Pronchery 
421*b077aed3SPierre Pronchery     methdata.libctx = libctx;
422*b077aed3SPierre Pronchery     methdata.tmp_store = NULL;
423*b077aed3SPierre Pronchery     method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
424*b077aed3SPierre Pronchery                                      name_id, NULL, properties,
425*b077aed3SPierre Pronchery                                      new_method, up_ref_method, free_method);
426*b077aed3SPierre Pronchery     dealloc_tmp_evp_method_store(methdata.tmp_store);
427*b077aed3SPierre Pronchery     return method;
428*b077aed3SPierre Pronchery }
429*b077aed3SPierre Pronchery 
430*b077aed3SPierre Pronchery /*
431*b077aed3SPierre Pronchery  * evp_generic_fetch_from_prov() is special, and only returns methods from
432*b077aed3SPierre Pronchery  * the given provider.
433*b077aed3SPierre Pronchery  * This is meant to be used when one method needs to fetch an associated
434*b077aed3SPierre Pronchery  * method.
435*b077aed3SPierre Pronchery  */
436*b077aed3SPierre Pronchery void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
437*b077aed3SPierre Pronchery                                   const char *name, const char *properties,
438*b077aed3SPierre Pronchery                                   void *(*new_method)(int name_id,
439*b077aed3SPierre Pronchery                                                       const OSSL_ALGORITHM *algodef,
440*b077aed3SPierre Pronchery                                                       OSSL_PROVIDER *prov),
441*b077aed3SPierre Pronchery                                   int (*up_ref_method)(void *),
442*b077aed3SPierre Pronchery                                   void (*free_method)(void *))
443*b077aed3SPierre Pronchery {
444*b077aed3SPierre Pronchery     struct evp_method_data_st methdata;
445*b077aed3SPierre Pronchery     void *method;
446*b077aed3SPierre Pronchery 
447*b077aed3SPierre Pronchery     methdata.libctx = ossl_provider_libctx(prov);
448*b077aed3SPierre Pronchery     methdata.tmp_store = NULL;
449*b077aed3SPierre Pronchery     method = inner_evp_generic_fetch(&methdata, prov, operation_id,
450*b077aed3SPierre Pronchery                                      0, name, properties,
451*b077aed3SPierre Pronchery                                      new_method, up_ref_method, free_method);
452*b077aed3SPierre Pronchery     dealloc_tmp_evp_method_store(methdata.tmp_store);
453*b077aed3SPierre Pronchery     return method;
454*b077aed3SPierre Pronchery }
455*b077aed3SPierre Pronchery 
456*b077aed3SPierre Pronchery int evp_method_store_cache_flush(OSSL_LIB_CTX *libctx)
457*b077aed3SPierre Pronchery {
458*b077aed3SPierre Pronchery     OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
459*b077aed3SPierre Pronchery 
460*b077aed3SPierre Pronchery     if (store != NULL)
461*b077aed3SPierre Pronchery         return ossl_method_store_cache_flush_all(store);
462*b077aed3SPierre Pronchery     return 1;
463*b077aed3SPierre Pronchery }
464*b077aed3SPierre Pronchery 
465*b077aed3SPierre Pronchery int evp_method_store_remove_all_provided(const OSSL_PROVIDER *prov)
466*b077aed3SPierre Pronchery {
467*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
468*b077aed3SPierre Pronchery     OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
469*b077aed3SPierre Pronchery 
470*b077aed3SPierre Pronchery     if (store != NULL)
471*b077aed3SPierre Pronchery         return ossl_method_store_remove_all_provided(store, prov);
472*b077aed3SPierre Pronchery     return 1;
473*b077aed3SPierre Pronchery }
474*b077aed3SPierre Pronchery 
475*b077aed3SPierre Pronchery static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
476*b077aed3SPierre Pronchery                                              OSSL_PROPERTY_LIST *def_prop,
477*b077aed3SPierre Pronchery                                              int loadconfig,
478*b077aed3SPierre Pronchery                                              int mirrored)
479*b077aed3SPierre Pronchery {
480*b077aed3SPierre Pronchery     OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
481*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
482*b077aed3SPierre Pronchery 
483*b077aed3SPierre Pronchery     if (plp != NULL && store != NULL) {
484*b077aed3SPierre Pronchery #ifndef FIPS_MODULE
485*b077aed3SPierre Pronchery         char *propstr = NULL;
486*b077aed3SPierre Pronchery         size_t strsz;
487*b077aed3SPierre Pronchery 
488*b077aed3SPierre Pronchery         if (mirrored) {
489*b077aed3SPierre Pronchery             if (ossl_global_properties_no_mirrored(libctx))
490*b077aed3SPierre Pronchery                 return 0;
491*b077aed3SPierre Pronchery         } else {
492*b077aed3SPierre Pronchery             /*
493*b077aed3SPierre Pronchery              * These properties have been explicitly set on this libctx, so
494*b077aed3SPierre Pronchery              * don't allow any mirroring from a parent libctx.
495*b077aed3SPierre Pronchery              */
496*b077aed3SPierre Pronchery             ossl_global_properties_stop_mirroring(libctx);
497*b077aed3SPierre Pronchery         }
498*b077aed3SPierre Pronchery 
499*b077aed3SPierre Pronchery         strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0);
500*b077aed3SPierre Pronchery         if (strsz > 0)
501*b077aed3SPierre Pronchery             propstr = OPENSSL_malloc(strsz);
502*b077aed3SPierre Pronchery         if (propstr == NULL) {
503*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
504*b077aed3SPierre Pronchery             return 0;
505*b077aed3SPierre Pronchery         }
506*b077aed3SPierre Pronchery         if (ossl_property_list_to_string(libctx, def_prop, propstr,
507*b077aed3SPierre Pronchery                                          strsz) == 0) {
508*b077aed3SPierre Pronchery             OPENSSL_free(propstr);
509*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
510*b077aed3SPierre Pronchery             return 0;
511*b077aed3SPierre Pronchery         }
512*b077aed3SPierre Pronchery         ossl_provider_default_props_update(libctx, propstr);
513*b077aed3SPierre Pronchery         OPENSSL_free(propstr);
514*b077aed3SPierre Pronchery #endif
515*b077aed3SPierre Pronchery         ossl_property_free(*plp);
516*b077aed3SPierre Pronchery         *plp = def_prop;
517*b077aed3SPierre Pronchery         if (store != NULL)
518*b077aed3SPierre Pronchery             return ossl_method_store_cache_flush_all(store);
519*b077aed3SPierre Pronchery     }
520*b077aed3SPierre Pronchery     ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
521*b077aed3SPierre Pronchery     return 0;
522*b077aed3SPierre Pronchery }
523*b077aed3SPierre Pronchery 
524*b077aed3SPierre Pronchery int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
525*b077aed3SPierre Pronchery                                    int loadconfig, int mirrored)
526*b077aed3SPierre Pronchery {
527*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST *pl = NULL;
528*b077aed3SPierre Pronchery 
529*b077aed3SPierre Pronchery     if (propq != NULL && (pl = ossl_parse_query(libctx, propq, 1)) == NULL) {
530*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
531*b077aed3SPierre Pronchery         return 0;
532*b077aed3SPierre Pronchery     }
533*b077aed3SPierre Pronchery     if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) {
534*b077aed3SPierre Pronchery         ossl_property_free(pl);
535*b077aed3SPierre Pronchery         return 0;
536*b077aed3SPierre Pronchery     }
537*b077aed3SPierre Pronchery     return 1;
538*b077aed3SPierre Pronchery }
539*b077aed3SPierre Pronchery 
540*b077aed3SPierre Pronchery int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
541*b077aed3SPierre Pronchery {
542*b077aed3SPierre Pronchery     return evp_set_default_properties_int(libctx, propq, 1, 0);
543*b077aed3SPierre Pronchery }
544*b077aed3SPierre Pronchery 
545*b077aed3SPierre Pronchery static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq,
546*b077aed3SPierre Pronchery                                         int loadconfig)
547*b077aed3SPierre Pronchery {
548*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
549*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST *pl1, *pl2;
550*b077aed3SPierre Pronchery 
551*b077aed3SPierre Pronchery     if (propq == NULL)
552*b077aed3SPierre Pronchery         return 1;
553*b077aed3SPierre Pronchery     if (plp == NULL || *plp == NULL)
554*b077aed3SPierre Pronchery         return evp_set_default_properties_int(libctx, propq, 0, 0);
555*b077aed3SPierre Pronchery     if ((pl1 = ossl_parse_query(libctx, propq, 1)) == NULL) {
556*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
557*b077aed3SPierre Pronchery         return 0;
558*b077aed3SPierre Pronchery     }
559*b077aed3SPierre Pronchery     pl2 = ossl_property_merge(pl1, *plp);
560*b077aed3SPierre Pronchery     ossl_property_free(pl1);
561*b077aed3SPierre Pronchery     if (pl2 == NULL) {
562*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
563*b077aed3SPierre Pronchery         return 0;
564*b077aed3SPierre Pronchery     }
565*b077aed3SPierre Pronchery     if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) {
566*b077aed3SPierre Pronchery         ossl_property_free(pl2);
567*b077aed3SPierre Pronchery         return 0;
568*b077aed3SPierre Pronchery     }
569*b077aed3SPierre Pronchery     return 1;
570*b077aed3SPierre Pronchery }
571*b077aed3SPierre Pronchery 
572*b077aed3SPierre Pronchery static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx,
573*b077aed3SPierre Pronchery                                            const char *prop_name)
574*b077aed3SPierre Pronchery {
575*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1);
576*b077aed3SPierre Pronchery 
577*b077aed3SPierre Pronchery     return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp);
578*b077aed3SPierre Pronchery }
579*b077aed3SPierre Pronchery 
580*b077aed3SPierre Pronchery int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx)
581*b077aed3SPierre Pronchery {
582*b077aed3SPierre Pronchery     return evp_default_property_is_enabled(libctx, "fips");
583*b077aed3SPierre Pronchery }
584*b077aed3SPierre Pronchery 
585*b077aed3SPierre Pronchery int evp_default_properties_enable_fips_int(OSSL_LIB_CTX *libctx, int enable,
586*b077aed3SPierre Pronchery                                            int loadconfig)
587*b077aed3SPierre Pronchery {
588*b077aed3SPierre Pronchery     const char *query = (enable != 0) ? "fips=yes" : "-fips";
589*b077aed3SPierre Pronchery 
590*b077aed3SPierre Pronchery     return evp_default_properties_merge(libctx, query, loadconfig);
591*b077aed3SPierre Pronchery }
592*b077aed3SPierre Pronchery 
593*b077aed3SPierre Pronchery int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable)
594*b077aed3SPierre Pronchery {
595*b077aed3SPierre Pronchery     return evp_default_properties_enable_fips_int(libctx, enable, 1);
596*b077aed3SPierre Pronchery }
597*b077aed3SPierre Pronchery 
598*b077aed3SPierre Pronchery char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig)
599*b077aed3SPierre Pronchery {
600*b077aed3SPierre Pronchery     OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
601*b077aed3SPierre Pronchery     char *propstr = NULL;
602*b077aed3SPierre Pronchery     size_t sz;
603*b077aed3SPierre Pronchery 
604*b077aed3SPierre Pronchery     if (plp == NULL)
605*b077aed3SPierre Pronchery         return OPENSSL_strdup("");
606*b077aed3SPierre Pronchery 
607*b077aed3SPierre Pronchery     sz = ossl_property_list_to_string(libctx, *plp, NULL, 0);
608*b077aed3SPierre Pronchery     if (sz == 0) {
609*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
610*b077aed3SPierre Pronchery         return NULL;
611*b077aed3SPierre Pronchery     }
612*b077aed3SPierre Pronchery 
613*b077aed3SPierre Pronchery     propstr = OPENSSL_malloc(sz);
614*b077aed3SPierre Pronchery     if (propstr == NULL) {
615*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
616*b077aed3SPierre Pronchery         return NULL;
617*b077aed3SPierre Pronchery     }
618*b077aed3SPierre Pronchery     if (ossl_property_list_to_string(libctx, *plp, propstr, sz) == 0) {
619*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
620*b077aed3SPierre Pronchery         OPENSSL_free(propstr);
621*b077aed3SPierre Pronchery         return NULL;
622*b077aed3SPierre Pronchery     }
623*b077aed3SPierre Pronchery     return propstr;
624*b077aed3SPierre Pronchery }
625*b077aed3SPierre Pronchery 
626*b077aed3SPierre Pronchery struct filter_data_st {
627*b077aed3SPierre Pronchery     int operation_id;
628*b077aed3SPierre Pronchery     void (*user_fn)(void *method, void *arg);
629*b077aed3SPierre Pronchery     void *user_arg;
630*b077aed3SPierre Pronchery };
631*b077aed3SPierre Pronchery 
632*b077aed3SPierre Pronchery static void filter_on_operation_id(int id, void *method, void *arg)
633*b077aed3SPierre Pronchery {
634*b077aed3SPierre Pronchery     struct filter_data_st *data = arg;
635*b077aed3SPierre Pronchery 
636*b077aed3SPierre Pronchery     if ((id & METHOD_ID_OPERATION_MASK) == data->operation_id)
637*b077aed3SPierre Pronchery         data->user_fn(method, data->user_arg);
638*b077aed3SPierre Pronchery }
639*b077aed3SPierre Pronchery 
640*b077aed3SPierre Pronchery void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
641*b077aed3SPierre Pronchery                         void (*user_fn)(void *method, void *arg),
642*b077aed3SPierre Pronchery                         void *user_arg,
643*b077aed3SPierre Pronchery                         void *(*new_method)(int name_id,
644*b077aed3SPierre Pronchery                                             const OSSL_ALGORITHM *algodef,
645*b077aed3SPierre Pronchery                                             OSSL_PROVIDER *prov),
646*b077aed3SPierre Pronchery                         int (*up_ref_method)(void *),
647*b077aed3SPierre Pronchery                         void (*free_method)(void *))
648*b077aed3SPierre Pronchery {
649*b077aed3SPierre Pronchery     struct evp_method_data_st methdata;
650*b077aed3SPierre Pronchery     struct filter_data_st data;
651*b077aed3SPierre Pronchery 
652*b077aed3SPierre Pronchery     methdata.libctx = libctx;
653*b077aed3SPierre Pronchery     methdata.tmp_store = NULL;
654*b077aed3SPierre Pronchery     (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, 0, NULL, NULL,
655*b077aed3SPierre Pronchery                                   new_method, up_ref_method, free_method);
656*b077aed3SPierre Pronchery 
657*b077aed3SPierre Pronchery     data.operation_id = operation_id;
658*b077aed3SPierre Pronchery     data.user_fn = user_fn;
659*b077aed3SPierre Pronchery     data.user_arg = user_arg;
660*b077aed3SPierre Pronchery     if (methdata.tmp_store != NULL)
661*b077aed3SPierre Pronchery         ossl_method_store_do_all(methdata.tmp_store, &filter_on_operation_id,
662*b077aed3SPierre Pronchery                                  &data);
663*b077aed3SPierre Pronchery     ossl_method_store_do_all(get_evp_method_store(libctx),
664*b077aed3SPierre Pronchery                              &filter_on_operation_id, &data);
665*b077aed3SPierre Pronchery     dealloc_tmp_evp_method_store(methdata.tmp_store);
666*b077aed3SPierre Pronchery }
667*b077aed3SPierre Pronchery 
668*b077aed3SPierre Pronchery int evp_is_a(OSSL_PROVIDER *prov, int number,
669*b077aed3SPierre Pronchery              const char *legacy_name, const char *name)
670*b077aed3SPierre Pronchery {
671*b077aed3SPierre Pronchery     /*
672*b077aed3SPierre Pronchery      * For a |prov| that is NULL, the library context will be NULL
673*b077aed3SPierre Pronchery      */
674*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
675*b077aed3SPierre Pronchery     OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
676*b077aed3SPierre Pronchery 
677*b077aed3SPierre Pronchery     if (prov == NULL)
678*b077aed3SPierre Pronchery         number = ossl_namemap_name2num(namemap, legacy_name);
679*b077aed3SPierre Pronchery     return ossl_namemap_name2num(namemap, name) == number;
680*b077aed3SPierre Pronchery }
681*b077aed3SPierre Pronchery 
682*b077aed3SPierre Pronchery int evp_names_do_all(OSSL_PROVIDER *prov, int number,
683*b077aed3SPierre Pronchery                      void (*fn)(const char *name, void *data),
684*b077aed3SPierre Pronchery                      void *data)
685*b077aed3SPierre Pronchery {
686*b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
687*b077aed3SPierre Pronchery     OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
688*b077aed3SPierre Pronchery 
689*b077aed3SPierre Pronchery     return ossl_namemap_doall_names(namemap, number, fn, data);
690*b077aed3SPierre Pronchery }
691