evp_fetch.c 24 KB

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