serializer_meth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * Copyright 2019 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 <openssl/core.h>
  10. #include <openssl/core_numbers.h>
  11. #include <openssl/serializer.h>
  12. #include <openssl/ui.h>
  13. #include "internal/core.h"
  14. #include "internal/namemap.h"
  15. #include "internal/property.h"
  16. #include "internal/provider.h"
  17. #include "crypto/serializer.h"
  18. #include "serializer_local.h"
  19. /*
  20. * Serializer can have multiple names, separated with colons in a name string
  21. */
  22. #define NAME_SEPARATOR ':'
  23. /* Simple method structure constructor and destructor */
  24. static OSSL_SERIALIZER *ossl_serializer_new(void)
  25. {
  26. OSSL_SERIALIZER *ser = NULL;
  27. if ((ser = OPENSSL_zalloc(sizeof(*ser))) == NULL
  28. || (ser->lock = CRYPTO_THREAD_lock_new()) == NULL) {
  29. OSSL_SERIALIZER_free(ser);
  30. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
  31. return NULL;
  32. }
  33. ser->refcnt = 1;
  34. return ser;
  35. }
  36. int OSSL_SERIALIZER_up_ref(OSSL_SERIALIZER *ser)
  37. {
  38. int ref = 0;
  39. CRYPTO_UP_REF(&ser->refcnt, &ref, ser->lock);
  40. return 1;
  41. }
  42. void OSSL_SERIALIZER_free(OSSL_SERIALIZER *ser)
  43. {
  44. int ref = 0;
  45. if (ser == NULL)
  46. return;
  47. CRYPTO_DOWN_REF(&ser->refcnt, &ref, ser->lock);
  48. if (ref > 0)
  49. return;
  50. ossl_provider_free(ser->prov);
  51. CRYPTO_THREAD_lock_free(ser->lock);
  52. OPENSSL_free(ser);
  53. }
  54. /* Permanent serializer method store, constructor and destructor */
  55. static void serializer_store_free(void *vstore)
  56. {
  57. ossl_method_store_free(vstore);
  58. }
  59. static void *serializer_store_new(OPENSSL_CTX *ctx)
  60. {
  61. return ossl_method_store_new(ctx);
  62. }
  63. static const OPENSSL_CTX_METHOD serializer_store_method = {
  64. serializer_store_new,
  65. serializer_store_free,
  66. };
  67. /* Data to be passed through ossl_method_construct() */
  68. struct serializer_data_st {
  69. OPENSSL_CTX *libctx;
  70. OSSL_METHOD_CONSTRUCT_METHOD *mcm;
  71. int id; /* For get_serializer_from_store() */
  72. const char *names; /* For get_serializer_from_store() */
  73. const char *propquery; /* For get_serializer_from_store() */
  74. };
  75. /*
  76. * Generic routines to fetch / create SERIALIZER methods with
  77. * ossl_method_construct()
  78. */
  79. /* Temporary serializer method store, constructor and destructor */
  80. static void *alloc_tmp_serializer_store(OPENSSL_CTX *ctx)
  81. {
  82. return ossl_method_store_new(ctx);
  83. }
  84. static void dealloc_tmp_serializer_store(void *store)
  85. {
  86. if (store != NULL)
  87. ossl_method_store_free(store);
  88. }
  89. /* Get the permanent serializer store */
  90. static OSSL_METHOD_STORE *get_serializer_store(OPENSSL_CTX *libctx)
  91. {
  92. return openssl_ctx_get_data(libctx, OPENSSL_CTX_SERIALIZER_STORE_INDEX,
  93. &serializer_store_method);
  94. }
  95. /* Get serializer methods from a store, or put one in */
  96. static void *get_serializer_from_store(OPENSSL_CTX *libctx, void *store,
  97. void *data)
  98. {
  99. struct serializer_data_st *methdata = data;
  100. void *method = NULL;
  101. int id;
  102. if ((id = methdata->id) == 0) {
  103. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  104. id = ossl_namemap_name2num(namemap, methdata->names);
  105. }
  106. if (store == NULL
  107. && (store = get_serializer_store(libctx)) == NULL)
  108. return NULL;
  109. if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
  110. return NULL;
  111. return method;
  112. }
  113. static int put_serializer_in_store(OPENSSL_CTX *libctx, void *store,
  114. void *method, const OSSL_PROVIDER *prov,
  115. int operation_id, const char *names,
  116. const char *propdef, void *unused)
  117. {
  118. OSSL_NAMEMAP *namemap;
  119. int id;
  120. if ((namemap = ossl_namemap_stored(libctx)) == NULL
  121. || (id = ossl_namemap_name2num(namemap, names)) == 0)
  122. return 0;
  123. if (store == NULL && (store = get_serializer_store(libctx)) == NULL)
  124. return 0;
  125. return ossl_method_store_add(store, prov, id, propdef, method,
  126. (int (*)(void *))OSSL_SERIALIZER_up_ref,
  127. (void (*)(void *))OSSL_SERIALIZER_free);
  128. }
  129. /* Create and populate a serializer method */
  130. static void *serializer_from_dispatch(int id, const OSSL_ALGORITHM *algodef,
  131. OSSL_PROVIDER *prov)
  132. {
  133. OSSL_SERIALIZER *ser = NULL;
  134. const OSSL_DISPATCH *fns = algodef->implementation;
  135. if ((ser = ossl_serializer_new()) == NULL)
  136. return NULL;
  137. ser->id = id;
  138. ser->propdef = algodef->property_definition;
  139. for (; fns->function_id != 0; fns++) {
  140. switch (fns->function_id) {
  141. case OSSL_FUNC_SERIALIZER_NEWCTX:
  142. if (ser->newctx == NULL)
  143. ser->newctx =
  144. OSSL_get_OP_serializer_newctx(fns);
  145. break;
  146. case OSSL_FUNC_SERIALIZER_FREECTX:
  147. if (ser->freectx == NULL)
  148. ser->freectx =
  149. OSSL_get_OP_serializer_freectx(fns);
  150. break;
  151. case OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS:
  152. if (ser->set_ctx_params == NULL)
  153. ser->set_ctx_params =
  154. OSSL_get_OP_serializer_set_ctx_params(fns);
  155. break;
  156. case OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS:
  157. if (ser->settable_ctx_params == NULL)
  158. ser->settable_ctx_params =
  159. OSSL_get_OP_serializer_settable_ctx_params(fns);
  160. break;
  161. case OSSL_FUNC_SERIALIZER_SERIALIZE_DATA:
  162. if (ser->serialize_data == NULL)
  163. ser->serialize_data =
  164. OSSL_get_OP_serializer_serialize_data(fns);
  165. break;
  166. case OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT:
  167. if (ser->serialize_object == NULL)
  168. ser->serialize_object =
  169. OSSL_get_OP_serializer_serialize_object(fns);
  170. break;
  171. }
  172. }
  173. /*
  174. * Try to check that the method is sensible.
  175. * If you have a constructor, you must have a destructor and vice versa.
  176. * You must have at least one of the serializing driver functions.
  177. */
  178. if (!((ser->newctx == NULL && ser->freectx == NULL)
  179. || (ser->newctx != NULL && ser->freectx != NULL))
  180. || (ser->serialize_data == NULL && ser->serialize_object == NULL)) {
  181. OSSL_SERIALIZER_free(ser);
  182. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
  183. return NULL;
  184. }
  185. if (prov != NULL && !ossl_provider_up_ref(prov)) {
  186. OSSL_SERIALIZER_free(ser);
  187. return NULL;
  188. }
  189. ser->prov = prov;
  190. return ser;
  191. }
  192. /*
  193. * The core fetching functionality passes the names of the implementation.
  194. * This function is responsible to getting an identity number for them,
  195. * then call serializer_from_dispatch() with that identity number.
  196. */
  197. static void *construct_serializer(const OSSL_ALGORITHM *algodef,
  198. OSSL_PROVIDER *prov, void *unused)
  199. {
  200. /*
  201. * This function is only called if get_serializer_from_store() returned
  202. * NULL, so it's safe to say that of all the spots to create a new
  203. * namemap entry, this is it. Should the name already exist there, we
  204. * know that ossl_namemap_add() will return its corresponding number.
  205. */
  206. OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
  207. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  208. const char *names = algodef->algorithm_names;
  209. int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
  210. void *method = NULL;
  211. if (id != 0)
  212. method = serializer_from_dispatch(id, algodef, prov);
  213. return method;
  214. }
  215. /* Intermediary function to avoid ugly casts, used below */
  216. static void destruct_serializer(void *method, void *data)
  217. {
  218. OSSL_SERIALIZER_free(method);
  219. }
  220. static int up_ref_serializer(void *method)
  221. {
  222. return OSSL_SERIALIZER_up_ref(method);
  223. }
  224. static void free_serializer(void *method)
  225. {
  226. OSSL_SERIALIZER_free(method);
  227. }
  228. /* Fetching support. Can fetch by numeric identity or by name */
  229. static OSSL_SERIALIZER *inner_ossl_serializer_fetch(OPENSSL_CTX *libctx,
  230. int id, const char *name,
  231. const char *properties)
  232. {
  233. OSSL_METHOD_STORE *store = get_serializer_store(libctx);
  234. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  235. void *method = NULL;
  236. if (store == NULL || namemap == NULL)
  237. return NULL;
  238. /*
  239. * If we have been passed neither a name_id or a name, we have an
  240. * internal programming error.
  241. */
  242. if (!ossl_assert(id != 0 || name != NULL))
  243. return NULL;
  244. if (id == 0)
  245. id = ossl_namemap_name2num(namemap, name);
  246. if (id == 0
  247. || !ossl_method_store_cache_get(store, id, properties, &method)) {
  248. OSSL_METHOD_CONSTRUCT_METHOD mcm = {
  249. alloc_tmp_serializer_store,
  250. dealloc_tmp_serializer_store,
  251. get_serializer_from_store,
  252. put_serializer_in_store,
  253. construct_serializer,
  254. destruct_serializer
  255. };
  256. struct serializer_data_st mcmdata;
  257. mcmdata.libctx = libctx;
  258. mcmdata.mcm = &mcm;
  259. mcmdata.id = id;
  260. mcmdata.names = name;
  261. mcmdata.propquery = properties;
  262. if ((method = ossl_method_construct(libctx, OSSL_OP_SERIALIZER,
  263. 0 /* !force_cache */,
  264. &mcm, &mcmdata)) != NULL) {
  265. /*
  266. * If construction did create a method for us, we know that
  267. * there is a correct name_id and meth_id, since those have
  268. * already been calculated in get_serializer_from_store() and
  269. * put_serializer_in_store() above.
  270. */
  271. if (id == 0)
  272. id = ossl_namemap_name2num(namemap, name);
  273. ossl_method_store_cache_set(store, id, properties, method,
  274. up_ref_serializer, free_serializer);
  275. }
  276. }
  277. return method;
  278. }
  279. OSSL_SERIALIZER *OSSL_SERIALIZER_fetch(OPENSSL_CTX *libctx, const char *name,
  280. const char *properties)
  281. {
  282. return inner_ossl_serializer_fetch(libctx, 0, name, properties);
  283. }
  284. OSSL_SERIALIZER *ossl_serializer_fetch_by_number(OPENSSL_CTX *libctx, int id,
  285. const char *properties)
  286. {
  287. return inner_ossl_serializer_fetch(libctx, id, NULL, properties);
  288. }
  289. /*
  290. * Library of basic method functions
  291. */
  292. const OSSL_PROVIDER *OSSL_SERIALIZER_provider(const OSSL_SERIALIZER *ser)
  293. {
  294. if (!ossl_assert(ser != NULL)) {
  295. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
  296. return 0;
  297. }
  298. return ser->prov;
  299. }
  300. const char *OSSL_SERIALIZER_properties(const OSSL_SERIALIZER *ser)
  301. {
  302. if (!ossl_assert(ser != NULL)) {
  303. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
  304. return 0;
  305. }
  306. return ser->propdef;
  307. }
  308. int OSSL_SERIALIZER_number(const OSSL_SERIALIZER *ser)
  309. {
  310. if (!ossl_assert(ser != NULL)) {
  311. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
  312. return 0;
  313. }
  314. return ser->id;
  315. }
  316. int OSSL_SERIALIZER_is_a(const OSSL_SERIALIZER *ser, const char *name)
  317. {
  318. if (ser->prov != NULL) {
  319. OPENSSL_CTX *libctx = ossl_provider_library_context(ser->prov);
  320. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  321. return ossl_namemap_name2num(namemap, name) == ser->id;
  322. }
  323. return 0;
  324. }
  325. struct serializer_do_all_data_st {
  326. void (*user_fn)(void *method, void *arg);
  327. void *user_arg;
  328. };
  329. static void serializer_do_one(OSSL_PROVIDER *provider,
  330. const OSSL_ALGORITHM *algodef,
  331. int no_store, void *vdata)
  332. {
  333. struct serializer_do_all_data_st *data = vdata;
  334. OPENSSL_CTX *libctx = ossl_provider_library_context(provider);
  335. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  336. const char *names = algodef->algorithm_names;
  337. int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
  338. void *method = NULL;
  339. if (id != 0)
  340. method =
  341. serializer_from_dispatch(id, algodef, provider);
  342. if (method != NULL) {
  343. data->user_fn(method, data->user_arg);
  344. OSSL_SERIALIZER_free(method);
  345. }
  346. }
  347. void OSSL_SERIALIZER_do_all_provided(OPENSSL_CTX *libctx,
  348. void (*fn)(OSSL_SERIALIZER *ser,
  349. void *arg),
  350. void *arg)
  351. {
  352. struct serializer_do_all_data_st data;
  353. data.user_fn = (void (*)(void *, void *))fn;
  354. data.user_arg = arg;
  355. ossl_algorithm_do_all(libctx, OSSL_OP_SERIALIZER, NULL,
  356. serializer_do_one, &data);
  357. }
  358. void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *ser,
  359. void (*fn)(const char *name, void *data),
  360. void *data)
  361. {
  362. if (ser == NULL)
  363. return;
  364. if (ser->prov != NULL) {
  365. OPENSSL_CTX *libctx = ossl_provider_library_context(ser->prov);
  366. OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
  367. ossl_namemap_doall_names(namemap, ser->id, fn, data);
  368. }
  369. }
  370. const OSSL_PARAM *OSSL_SERIALIZER_settable_ctx_params(OSSL_SERIALIZER *ser)
  371. {
  372. if (ser != NULL && ser->settable_ctx_params != NULL)
  373. return ser->settable_ctx_params();
  374. return NULL;
  375. }
  376. /*
  377. * Serializer context support
  378. */
  379. /*
  380. * |ser| value NULL is valid, and signifies that there is no serializer.
  381. * This is useful to provide fallback mechanisms.
  382. * Functions that want to verify if there is a serializer can do so with
  383. * OSSL_SERIALIZER_CTX_get_serializer()
  384. */
  385. OSSL_SERIALIZER_CTX *OSSL_SERIALIZER_CTX_new(OSSL_SERIALIZER *ser)
  386. {
  387. OSSL_SERIALIZER_CTX *ctx;
  388. if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
  389. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_MALLOC_FAILURE);
  390. return NULL;
  391. }
  392. ctx->ser = ser;
  393. if (ser != NULL && ser->newctx != NULL) {
  394. const OSSL_PROVIDER *prov = OSSL_SERIALIZER_provider(ser);
  395. void *provctx = ossl_provider_ctx(prov);
  396. if (OSSL_SERIALIZER_up_ref(ser)) {
  397. ctx->serctx = ser->newctx(provctx);
  398. } else {
  399. OSSL_SERIALIZER_free(ser);
  400. OPENSSL_free(ctx);
  401. ctx = NULL;
  402. }
  403. }
  404. return ctx;
  405. }
  406. const OSSL_SERIALIZER *
  407. OSSL_SERIALIZER_CTX_get_serializer(OSSL_SERIALIZER_CTX *ctx)
  408. {
  409. if (!ossl_assert(ctx != NULL)) {
  410. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
  411. return 0;
  412. }
  413. return ctx->ser;
  414. }
  415. int OSSL_SERIALIZER_CTX_set_params(OSSL_SERIALIZER_CTX *ctx,
  416. const OSSL_PARAM params[])
  417. {
  418. if (!ossl_assert(ctx != NULL)) {
  419. ERR_raise(ERR_LIB_OSSL_SERIALIZER, ERR_R_PASSED_NULL_PARAMETER);
  420. return 0;
  421. }
  422. if (ctx->ser != NULL && ctx->ser->set_ctx_params != NULL)
  423. return ctx->ser->set_ctx_params(ctx->serctx, params);
  424. return 0;
  425. }
  426. void OSSL_SERIALIZER_CTX_free(OSSL_SERIALIZER_CTX *ctx)
  427. {
  428. if (ctx != NULL) {
  429. if (ctx->ser != NULL && ctx->ser->freectx != NULL)
  430. ctx->ser->freectx(ctx->serctx);
  431. OSSL_SERIALIZER_free(ctx->ser);
  432. UI_destroy_method(ctx->allocated_ui_method);
  433. OPENSSL_free(ctx);
  434. }
  435. }