]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/evp_fetch.c
todo: remove TODO(3.0) from the sources.
[thirdparty/openssl.git] / crypto / evp / evp_fetch.c
CommitLineData
c13d2ab4 1/*
4333b89f 2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
c13d2ab4
RL
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 <stddef.h>
50cd4768 11#include <openssl/types.h>
c13d2ab4
RL
12#include <openssl/evp.h>
13#include <openssl/core.h>
14#include "internal/cryptlib.h"
15#include "internal/thread_once.h"
c13d2ab4
RL
16#include "internal/property.h"
17#include "internal/core.h"
f7c16d48 18#include "internal/provider.h"
baff732d 19#include "internal/namemap.h"
04cb5ec0 20#include "internal/property.h"
706457b7
DMSP
21#include "crypto/evp.h" /* evp_local.h needs it */
22#include "evp_local.h"
c13d2ab4 23
695d195b
RL
24#define NAME_SEPARATOR ':'
25
181ea366 26static void evp_method_store_free(void *vstore)
c13d2ab4
RL
27{
28 ossl_method_store_free(vstore);
29}
30
b4250010 31static void *evp_method_store_new(OSSL_LIB_CTX *ctx)
c13d2ab4 32{
1aedc35f 33 return ossl_method_store_new(ctx);
c13d2ab4
RL
34}
35
36
b4250010 37static const OSSL_LIB_CTX_METHOD evp_method_store_method = {
a16d2174 38 /* We want evp_method_store to be cleaned up before the provider store */
8c627075 39 OSSL_LIB_CTX_METHOD_PRIORITY_2,
181ea366
RL
40 evp_method_store_new,
41 evp_method_store_free,
c13d2ab4
RL
42};
43
c13d2ab4 44/* Data to be passed through ossl_method_construct() */
181ea366 45struct evp_method_data_st {
b4250010 46 OSSL_LIB_CTX *libctx;
c13d2ab4 47 OSSL_METHOD_CONSTRUCT_METHOD *mcm;
181ea366
RL
48 int operation_id; /* For get_evp_method_from_store() */
49 int name_id; /* For get_evp_method_from_store() */
50 const char *names; /* For get_evp_method_from_store() */
51 const char *propquery; /* For get_evp_method_from_store() */
ec0ce188 52
e3a2ba75 53 unsigned int flag_construct_error_occurred : 1;
ec0ce188 54
309a78aa
RL
55 void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *,
56 OSSL_PROVIDER *);
c13d2ab4
RL
57 int (*refcnt_up_method)(void *method);
58 void (*destruct_method)(void *method);
59};
60
61/*
62 * Generic routines to fetch / create EVP methods with ossl_method_construct()
63 */
b4250010 64static void *alloc_tmp_evp_method_store(OSSL_LIB_CTX *ctx)
c13d2ab4 65{
1aedc35f 66 return ossl_method_store_new(ctx);
c13d2ab4
RL
67}
68
181ea366 69 static void dealloc_tmp_evp_method_store(void *store)
c13d2ab4
RL
70{
71 if (store != NULL)
72 ossl_method_store_free(store);
73}
74
b4250010 75static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx)
c13d2ab4 76{
b4250010
DMSP
77 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX,
78 &evp_method_store_method);
c13d2ab4
RL
79}
80
2ccb1b4e 81/*
64f849f4
DMSP
82 * To identify the method in the EVP method store, we mix the name identity
83 * with the operation identity, under the assumption that we don't have more
181ea366 84 * than 2^24 names or more than 2^8 operation types.
2ccb1b4e
RL
85 *
86 * The resulting identity is a 32-bit integer, composed like this:
87 *
88 * +---------24 bits--------+-8 bits-+
89 * | name identity | op id |
90 * +------------------------+--------+
91 */
b418980c 92static uint32_t evp_method_id(int name_id, unsigned int operation_id)
2ccb1b4e 93{
64f849f4
DMSP
94 if (!ossl_assert(name_id > 0 && name_id < (1 << 24))
95 || !ossl_assert(operation_id > 0 && operation_id < (1 << 8)))
2ccb1b4e
RL
96 return 0;
97 return ((name_id << 8) & 0xFFFFFF00) | (operation_id & 0x000000FF);
98}
99
b4250010 100static void *get_evp_method_from_store(OSSL_LIB_CTX *libctx, void *store,
181ea366 101 void *data)
c13d2ab4 102{
181ea366 103 struct evp_method_data_st *methdata = data;
c13d2ab4 104 void *method = NULL;
f7c16d48
RL
105 int name_id;
106 uint32_t meth_id;
c13d2ab4 107
f7c16d48 108 /*
181ea366
RL
109 * get_evp_method_from_store() is only called to try and get the method
110 * that evp_generic_fetch() is asking for, and the operation id as well
111 * as the name or name id are passed via methdata.
f7c16d48
RL
112 */
113 if ((name_id = methdata->name_id) == 0) {
114 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
695d195b
RL
115 const char *names = methdata->names;
116 const char *q = strchr(names, NAME_SEPARATOR);
117 size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
f7c16d48
RL
118
119 if (namemap == 0)
120 return NULL;
695d195b 121 name_id = ossl_namemap_name2num_n(namemap, names, l);
f7c16d48
RL
122 }
123
124 if (name_id == 0
b418980c 125 || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
c13d2ab4
RL
126 return NULL;
127
f7c16d48 128 if (store == NULL
181ea366 129 && (store = get_evp_method_store(libctx)) == NULL)
2e49c054
RL
130 return NULL;
131
bdbf2df2
P
132 if (!ossl_method_store_fetch(store, meth_id, methdata->propquery,
133 &method))
134 return NULL;
c13d2ab4
RL
135 return method;
136}
137
b4250010 138static int put_evp_method_in_store(OSSL_LIB_CTX *libctx, void *store,
181ea366
RL
139 void *method, const OSSL_PROVIDER *prov,
140 int operation_id, const char *names,
141 const char *propdef, void *data)
c13d2ab4 142{
181ea366 143 struct evp_method_data_st *methdata = data;
2e49c054 144 OSSL_NAMEMAP *namemap;
f7c16d48
RL
145 int name_id;
146 uint32_t meth_id;
695d195b 147 size_t l = 0;
dc46e3dd 148
f7c16d48 149 /*
181ea366
RL
150 * put_evp_method_in_store() is only called with an EVP method that was
151 * successfully created by construct_method() below, which means that
152 * all the names should already be stored in the namemap with the same
153 * numeric identity, so just use the first to get that identity.
f7c16d48 154 */
695d195b
RL
155 if (names != NULL) {
156 const char *q = strchr(names, NAME_SEPARATOR);
157
158 l = (q == NULL ? strlen(names) : (size_t)(q - names));
159 }
160
f7c16d48 161 if ((namemap = ossl_namemap_stored(libctx)) == NULL
695d195b 162 || (name_id = ossl_namemap_name2num_n(namemap, names, l)) == 0
b418980c 163 || (meth_id = evp_method_id(name_id, operation_id)) == 0)
dc46e3dd 164 return 0;
c13d2ab4
RL
165
166 if (store == NULL
181ea366 167 && (store = get_evp_method_store(libctx)) == NULL)
c13d2ab4
RL
168 return 0;
169
f7c16d48 170 return ossl_method_store_add(store, prov, meth_id, propdef, method,
b1d40ddf
RL
171 methdata->refcnt_up_method,
172 methdata->destruct_method);
c13d2ab4
RL
173}
174
f7c16d48
RL
175/*
176 * The core fetching functionality passes the name of the implementation.
177 * This function is responsible to getting an identity number for it.
178 */
36fa4d8a 179static void *construct_evp_method(const OSSL_ALGORITHM *algodef,
181ea366 180 OSSL_PROVIDER *prov, void *data)
c13d2ab4 181{
f7c16d48 182 /*
181ea366 183 * This function is only called if get_evp_method_from_store() returned
f7c16d48
RL
184 * NULL, so it's safe to say that of all the spots to create a new
185 * namemap entry, this is it. Should the name already exist there, we
3d83c735
RL
186 * know that ossl_namemap_add_name() will return its corresponding
187 * number.
f7c16d48 188 */
181ea366 189 struct evp_method_data_st *methdata = data;
a829b735 190 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
f7c16d48 191 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
36fa4d8a 192 const char *names = algodef->algorithm_names;
3d83c735 193 int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
ec0ce188 194 void *method;
c13d2ab4 195
695d195b
RL
196 if (name_id == 0)
197 return NULL;
ec0ce188 198
309a78aa 199 method = methdata->method_from_algorithm(name_id, algodef, prov);
ec0ce188
RL
200
201 /*
202 * Flag to indicate that there was actual construction errors. This
203 * helps inner_evp_generic_fetch() determine what error it should
204 * record on inaccessible algorithms.
205 */
206 if (method == NULL)
e3a2ba75 207 methdata->flag_construct_error_occurred = 1;
ec0ce188
RL
208
209 return method;
c13d2ab4
RL
210}
211
181ea366 212static void destruct_evp_method(void *method, void *data)
c13d2ab4 213{
181ea366 214 struct evp_method_data_st *methdata = data;
c13d2ab4
RL
215
216 methdata->destruct_method(method);
217}
218
181ea366 219static void *
b4250010 220inner_evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
181ea366
RL
221 int name_id, const char *name,
222 const char *properties,
223 void *(*new_method)(int name_id,
309a78aa 224 const OSSL_ALGORITHM *algodef,
0ddf74bf 225 OSSL_PROVIDER *prov),
181ea366
RL
226 int (*up_ref_method)(void *),
227 void (*free_method)(void *))
c13d2ab4 228{
181ea366 229 OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
437ad983 230 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
f7c16d48 231 uint32_t meth_id = 0;
c13d2ab4 232 void *method = NULL;
ec0ce188 233 int unsupported = 0;
c13d2ab4 234
ec0ce188 235 if (store == NULL || namemap == NULL) {
d6d42cda 236 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
e019da7b 237 return NULL;
ec0ce188 238 }
e019da7b 239
2ccb1b4e
RL
240 /*
241 * If there's ever an operation_id == 0 passed, we have an internal
242 * programming error.
243 */
ec0ce188 244 if (!ossl_assert(operation_id > 0)) {
d6d42cda 245 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
2ccb1b4e 246 return NULL;
ec0ce188 247 }
2ccb1b4e
RL
248
249 /*
f7c16d48
RL
250 * If we have been passed neither a name_id or a name, we have an
251 * internal programming error.
252 */
ec0ce188 253 if (!ossl_assert(name_id != 0 || name != NULL)) {
d6d42cda 254 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
f7c16d48 255 return NULL;
ec0ce188 256 }
f7c16d48
RL
257
258 /* If we haven't received a name id yet, try to get one for the name */
259 if (name_id == 0)
260 name_id = ossl_namemap_name2num(namemap, name);
261
262 /*
181ea366 263 * If we have a name id, calculate a method id with evp_method_id().
f7c16d48 264 *
181ea366
RL
265 * evp_method_id returns 0 if we have too many operations (more than
266 * about 2^8) or too many names (more than about 2^24). In that case,
267 * we can't create any new method.
ec0ce188 268 * For all intents and purposes, this is an internal error.
2ccb1b4e 269 */
ec0ce188 270 if (name_id != 0 && (meth_id = evp_method_id(name_id, operation_id)) == 0) {
d6d42cda 271 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
2ccb1b4e 272 return NULL;
ec0ce188
RL
273 }
274
275 /*
276 * If we haven't found the name yet, chances are that the algorithm to
277 * be fetched is unsupported.
278 */
279 if (name_id == 0)
280 unsupported = 1;
2ccb1b4e 281
f7c16d48
RL
282 if (meth_id == 0
283 || !ossl_method_store_cache_get(store, meth_id, properties, &method)) {
c13d2ab4 284 OSSL_METHOD_CONSTRUCT_METHOD mcm = {
181ea366
RL
285 alloc_tmp_evp_method_store,
286 dealloc_tmp_evp_method_store,
287 get_evp_method_from_store,
288 put_evp_method_in_store,
289 construct_evp_method,
290 destruct_evp_method
c13d2ab4 291 };
181ea366 292 struct evp_method_data_st mcmdata;
c13d2ab4 293
c13d2ab4 294 mcmdata.mcm = &mcm;
baff732d 295 mcmdata.libctx = libctx;
f7c16d48
RL
296 mcmdata.operation_id = operation_id;
297 mcmdata.name_id = name_id;
695d195b 298 mcmdata.names = name;
f7c16d48 299 mcmdata.propquery = properties;
309a78aa 300 mcmdata.method_from_algorithm = new_method;
7c95390e 301 mcmdata.refcnt_up_method = up_ref_method;
c13d2ab4 302 mcmdata.destruct_method = free_method;
e3a2ba75 303 mcmdata.flag_construct_error_occurred = 0;
f7c16d48
RL
304 if ((method = ossl_method_construct(libctx, operation_id,
305 0 /* !force_cache */,
08607613 306 &mcm, &mcmdata)) != NULL) {
2ccb1b4e
RL
307 /*
308 * If construction did create a method for us, we know that
181ea366
RL
309 * there is a correct name_id and meth_id, since those have
310 * already been calculated in get_evp_method_from_store() and
311 * put_evp_method_in_store() above.
2ccb1b4e 312 */
f7c16d48
RL
313 if (name_id == 0)
314 name_id = ossl_namemap_name2num(namemap, name);
b418980c 315 meth_id = evp_method_id(name_id, operation_id);
bdbf2df2
P
316 ossl_method_store_cache_set(store, meth_id, properties, method,
317 up_ref_method, free_method);
2ccb1b4e 318 }
ec0ce188
RL
319
320 /*
321 * If we never were in the constructor, the algorithm to be fetched
322 * is unsupported.
323 */
e3a2ba75 324 unsupported = !mcmdata.flag_construct_error_occurred;
c13d2ab4
RL
325 }
326
ec0ce188 327 if (method == NULL) {
d6d42cda 328 int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
cb929645 329
ec0ce188
RL
330 if (name == NULL)
331 name = ossl_namemap_num2name(namemap, name_id, 0);
332 ERR_raise_data(ERR_LIB_EVP, code,
333 "%s, Algorithm (%s : %d), Properties (%s)",
d6d42cda 334 ossl_lib_ctx_get_descriptor(libctx),
ec0ce188
RL
335 name = NULL ? "<null>" : name, name_id,
336 properties == NULL ? "<null>" : properties);
337 }
338
339 return method;
cfbd76c1 340}
cfbd76c1 341
b4250010 342void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
f7c16d48
RL
343 const char *name, const char *properties,
344 void *(*new_method)(int name_id,
309a78aa 345 const OSSL_ALGORITHM *algodef,
0ddf74bf 346 OSSL_PROVIDER *prov),
f7c16d48
RL
347 int (*up_ref_method)(void *),
348 void (*free_method)(void *))
349{
ec0ce188
RL
350 return inner_evp_generic_fetch(libctx,
351 operation_id, 0, name, properties,
352 new_method, up_ref_method, free_method);
f7c16d48
RL
353}
354
355/*
356 * evp_generic_fetch_by_number() is special, and only returns methods for
357 * already known names, i.e. it refuses to work if no name_id can be found
358 * (it's considered an internal programming error).
359 * This is meant to be used when one method needs to fetch an associated
360 * other method.
361 */
b4250010 362void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id,
f7c16d48
RL
363 int name_id, const char *properties,
364 void *(*new_method)(int name_id,
309a78aa 365 const OSSL_ALGORITHM *algodef,
0ddf74bf 366 OSSL_PROVIDER *prov),
f7c16d48
RL
367 int (*up_ref_method)(void *),
368 void (*free_method)(void *))
369{
ec0ce188
RL
370 return inner_evp_generic_fetch(libctx,
371 operation_id, name_id, NULL,
372 properties, new_method, up_ref_method,
373 free_method);
f7c16d48
RL
374}
375
860ecfd7 376int evp_method_store_flush(OSSL_LIB_CTX *libctx)
04cb5ec0
SL
377{
378 OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
379
380 if (store != NULL)
860ecfd7
P
381 return ossl_method_store_flush_cache(store, 1);
382 return 1;
04cb5ec0
SL
383}
384
b4250010 385static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
e6c54619
MC
386 OSSL_PROPERTY_LIST *def_prop,
387 int loadconfig)
cb929645 388{
181ea366 389 OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
e6c54619 390 OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
f9e504e8
P
391
392 if (plp != NULL) {
393 ossl_property_free(*plp);
394 *plp = def_prop;
395 if (store != NULL)
860ecfd7 396 return ossl_method_store_flush_cache(store, 0);
f9e504e8
P
397 return 1;
398 }
9311d0c4 399 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
cb929645
RL
400 return 0;
401}
3d96a51c 402
b4250010 403int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
e6c54619 404 int loadconfig)
f9e504e8
P
405{
406 OSSL_PROPERTY_LIST *pl = NULL;
407
1e08f3ba 408 if (propq != NULL && (pl = ossl_parse_query(libctx, propq, 1)) == NULL) {
9311d0c4 409 ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
f9e504e8
P
410 return 0;
411 }
e6c54619 412 return evp_set_parsed_default_properties(libctx, pl, loadconfig);
f9e504e8
P
413}
414
b4250010 415int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
e6c54619
MC
416{
417 return evp_set_default_properties_int(libctx, propq, 1);
418}
e0624f0d 419
b4250010 420static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq)
e0624f0d 421{
e6c54619 422 OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1);
f9e504e8
P
423 OSSL_PROPERTY_LIST *pl1, *pl2;
424
425 if (propq == NULL)
426 return 1;
427 if (plp == NULL || *plp == NULL)
428 return EVP_set_default_properties(libctx, propq);
1e08f3ba 429 if ((pl1 = ossl_parse_query(libctx, propq, 1)) == NULL) {
9311d0c4 430 ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
f9e504e8
P
431 return 0;
432 }
433 pl2 = ossl_property_merge(pl1, *plp);
434 ossl_property_free(pl1);
435 if (pl2 == NULL) {
9311d0c4 436 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
f9e504e8
P
437 return 0;
438 }
e6c54619 439 return evp_set_parsed_default_properties(libctx, pl2, 0);
e0624f0d
SL
440}
441
b4250010 442static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx,
e0624f0d
SL
443 const char *prop_name)
444{
e6c54619 445 OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1);
e0624f0d 446
f9e504e8 447 return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp);
e0624f0d
SL
448}
449
b4250010 450int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx)
e0624f0d
SL
451{
452 return evp_default_property_is_enabled(libctx, "fips");
453}
454
b4250010 455int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable)
e0624f0d
SL
456{
457 const char *query = (enable != 0) ? "fips=yes" : "-fips";
458
459 return evp_default_properties_merge(libctx, query);
460}
461
462
3d96a51c
RL
463struct do_all_data_st {
464 void (*user_fn)(void *method, void *arg);
465 void *user_arg;
309a78aa 466 void *(*new_method)(const int name_id, const OSSL_ALGORITHM *algodef,
0ddf74bf 467 OSSL_PROVIDER *prov);
3d96a51c
RL
468 void (*free_method)(void *);
469};
470
471static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo,
472 int no_store, void *vdata)
473{
474 struct do_all_data_st *data = vdata;
a829b735 475 OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
f7c16d48 476 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
3d83c735
RL
477 int name_id = ossl_namemap_add_names(namemap, 0, algo->algorithm_names,
478 NAME_SEPARATOR);
f7c16d48
RL
479 void *method = NULL;
480
481 if (name_id != 0)
309a78aa 482 method = data->new_method(name_id, algo, provider);
3d96a51c
RL
483
484 if (method != NULL) {
485 data->user_fn(method, data->user_arg);
486 data->free_method(method);
487 }
488}
489
b4250010 490void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
3d96a51c
RL
491 void (*user_fn)(void *method, void *arg),
492 void *user_arg,
f7c16d48 493 void *(*new_method)(int name_id,
309a78aa 494 const OSSL_ALGORITHM *algodef,
0ddf74bf 495 OSSL_PROVIDER *prov),
3d96a51c
RL
496 void (*free_method)(void *))
497{
498 struct do_all_data_st data;
499
500 data.new_method = new_method;
501 data.free_method = free_method;
502 data.user_fn = user_fn;
503 data.user_arg = user_arg;
5a29b628
RL
504
505 /*
506 * No pre- or post-condition for this call, as this only creates methods
507 * temporarly and then promptly destroys them.
508 */
509 ossl_algorithm_do_all(libctx, operation_id, NULL, NULL, do_one, NULL,
510 &data);
3d96a51c 511}
f7c16d48 512
e4a1d023
RL
513int evp_is_a(OSSL_PROVIDER *prov, int number,
514 const char *legacy_name, const char *name)
7cfa1717 515{
e4a1d023
RL
516 /*
517 * For a |prov| that is NULL, the library context will be NULL
518 */
a829b735 519 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
7cfa1717
RL
520 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
521
e4a1d023
RL
522 if (prov == NULL)
523 number = ossl_namemap_name2num(namemap, legacy_name);
7cfa1717
RL
524 return ossl_namemap_name2num(namemap, name) == number;
525}
32040838 526
d84f5515
MC
527int evp_names_do_all(OSSL_PROVIDER *prov, int number,
528 void (*fn)(const char *name, void *data),
529 void *data)
32040838 530{
a829b735 531 OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
32040838
RL
532 OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
533
d84f5515 534 return ossl_namemap_doall_names(namemap, number, fn, data);
32040838 535}