2
0

eng_table.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (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 "internal/cryptlib.h"
  10. #include <openssl/evp.h>
  11. #include <openssl/lhash.h>
  12. #include "eng_local.h"
  13. /* The type of the items in the table */
  14. struct st_engine_pile {
  15. /* The 'nid' of this algorithm/mode */
  16. int nid;
  17. /* ENGINEs that implement this algorithm/mode. */
  18. STACK_OF(ENGINE) *sk;
  19. /* The default ENGINE to perform this algorithm/mode. */
  20. ENGINE *funct;
  21. /*
  22. * Zero if 'sk' is newer than the cached 'funct', non-zero otherwise
  23. */
  24. int uptodate;
  25. };
  26. /* The type exposed in eng_local.h */
  27. struct st_engine_table {
  28. LHASH_OF(ENGINE_PILE) piles;
  29. }; /* ENGINE_TABLE */
  30. typedef struct st_engine_pile_doall {
  31. engine_table_doall_cb *cb;
  32. void *arg;
  33. } ENGINE_PILE_DOALL;
  34. /* Global flags (ENGINE_TABLE_FLAG_***). */
  35. static unsigned int table_flags = 0;
  36. /* API function manipulating 'table_flags' */
  37. unsigned int ENGINE_get_table_flags(void)
  38. {
  39. return table_flags;
  40. }
  41. void ENGINE_set_table_flags(unsigned int flags)
  42. {
  43. table_flags = flags;
  44. }
  45. /* Internal functions for the "piles" hash table */
  46. static unsigned long engine_pile_hash(const ENGINE_PILE *c)
  47. {
  48. return c->nid;
  49. }
  50. static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
  51. {
  52. return a->nid - b->nid;
  53. }
  54. static int int_table_check(ENGINE_TABLE **t, int create)
  55. {
  56. LHASH_OF(ENGINE_PILE) *lh;
  57. if (*t)
  58. return 1;
  59. if (!create)
  60. return 0;
  61. if ((lh = lh_ENGINE_PILE_new(engine_pile_hash, engine_pile_cmp)) == NULL)
  62. return 0;
  63. *t = (ENGINE_TABLE *)lh;
  64. return 1;
  65. }
  66. /*
  67. * Privately exposed (via eng_local.h) functions for adding and/or removing
  68. * ENGINEs from the implementation table
  69. */
  70. int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
  71. ENGINE *e, const int *nids, int num_nids,
  72. int setdefault)
  73. {
  74. int ret = 0, added = 0;
  75. ENGINE_PILE tmplate, *fnd;
  76. CRYPTO_THREAD_write_lock(global_engine_lock);
  77. if (!(*table))
  78. added = 1;
  79. if (!int_table_check(table, 1))
  80. goto end;
  81. if (added)
  82. /* The cleanup callback needs to be added */
  83. engine_cleanup_add_first(cleanup);
  84. while (num_nids--) {
  85. tmplate.nid = *nids;
  86. fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
  87. if (!fnd) {
  88. fnd = OPENSSL_malloc(sizeof(*fnd));
  89. if (fnd == NULL)
  90. goto end;
  91. fnd->uptodate = 1;
  92. fnd->nid = *nids;
  93. fnd->sk = sk_ENGINE_new_null();
  94. if (!fnd->sk) {
  95. OPENSSL_free(fnd);
  96. goto end;
  97. }
  98. fnd->funct = NULL;
  99. (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
  100. if (lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate) != fnd) {
  101. sk_ENGINE_free(fnd->sk);
  102. OPENSSL_free(fnd);
  103. goto end;
  104. }
  105. }
  106. /* A registration shouldn't add duplicate entries */
  107. (void)sk_ENGINE_delete_ptr(fnd->sk, e);
  108. /*
  109. * if 'setdefault', this ENGINE goes to the head of the list
  110. */
  111. if (!sk_ENGINE_push(fnd->sk, e))
  112. goto end;
  113. /* "touch" this ENGINE_PILE */
  114. fnd->uptodate = 0;
  115. if (setdefault) {
  116. if (!engine_unlocked_init(e)) {
  117. ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
  118. ENGINE_R_INIT_FAILED);
  119. goto end;
  120. }
  121. if (fnd->funct)
  122. engine_unlocked_finish(fnd->funct, 0);
  123. fnd->funct = e;
  124. fnd->uptodate = 1;
  125. }
  126. nids++;
  127. }
  128. ret = 1;
  129. end:
  130. CRYPTO_THREAD_unlock(global_engine_lock);
  131. return ret;
  132. }
  133. static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)
  134. {
  135. int n;
  136. /* Iterate the 'c->sk' stack removing any occurrence of 'e' */
  137. while ((n = sk_ENGINE_find(pile->sk, e)) >= 0) {
  138. (void)sk_ENGINE_delete(pile->sk, n);
  139. pile->uptodate = 0;
  140. }
  141. if (pile->funct == e) {
  142. engine_unlocked_finish(e, 0);
  143. pile->funct = NULL;
  144. }
  145. }
  146. IMPLEMENT_LHASH_DOALL_ARG(ENGINE_PILE, ENGINE);
  147. void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
  148. {
  149. CRYPTO_THREAD_write_lock(global_engine_lock);
  150. if (int_table_check(table, 0))
  151. lh_ENGINE_PILE_doall_ENGINE(&(*table)->piles, int_unregister_cb, e);
  152. CRYPTO_THREAD_unlock(global_engine_lock);
  153. }
  154. static void int_cleanup_cb_doall(ENGINE_PILE *p)
  155. {
  156. if (!p)
  157. return;
  158. sk_ENGINE_free(p->sk);
  159. if (p->funct)
  160. engine_unlocked_finish(p->funct, 0);
  161. OPENSSL_free(p);
  162. }
  163. void engine_table_cleanup(ENGINE_TABLE **table)
  164. {
  165. CRYPTO_THREAD_write_lock(global_engine_lock);
  166. if (*table) {
  167. lh_ENGINE_PILE_doall(&(*table)->piles, int_cleanup_cb_doall);
  168. lh_ENGINE_PILE_free(&(*table)->piles);
  169. *table = NULL;
  170. }
  171. CRYPTO_THREAD_unlock(global_engine_lock);
  172. }
  173. /* return a functional reference for a given 'nid' */
  174. #ifndef ENGINE_TABLE_DEBUG
  175. ENGINE *engine_table_select(ENGINE_TABLE **table, int nid)
  176. #else
  177. ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
  178. int l)
  179. #endif
  180. {
  181. ENGINE *ret = NULL;
  182. ENGINE_PILE tmplate, *fnd = NULL;
  183. int initres, loop = 0;
  184. if (!(*table)) {
  185. #ifdef ENGINE_TABLE_DEBUG
  186. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
  187. "registered!\n", f, l, nid);
  188. #endif
  189. return NULL;
  190. }
  191. ERR_set_mark();
  192. CRYPTO_THREAD_write_lock(global_engine_lock);
  193. /*
  194. * Check again inside the lock otherwise we could race against cleanup
  195. * operations. But don't worry about a fprintf(stderr).
  196. */
  197. if (!int_table_check(table, 0))
  198. goto end;
  199. tmplate.nid = nid;
  200. fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
  201. if (!fnd)
  202. goto end;
  203. if (fnd->funct && engine_unlocked_init(fnd->funct)) {
  204. #ifdef ENGINE_TABLE_DEBUG
  205. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
  206. "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
  207. #endif
  208. ret = fnd->funct;
  209. goto end;
  210. }
  211. if (fnd->uptodate) {
  212. ret = fnd->funct;
  213. goto end;
  214. }
  215. trynext:
  216. ret = sk_ENGINE_value(fnd->sk, loop++);
  217. if (!ret) {
  218. #ifdef ENGINE_TABLE_DEBUG
  219. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
  220. "registered implementations would initialise\n", f, l, nid);
  221. #endif
  222. goto end;
  223. }
  224. /* Try to initialise the ENGINE? */
  225. if ((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
  226. initres = engine_unlocked_init(ret);
  227. else
  228. initres = 0;
  229. if (initres) {
  230. /* Update 'funct' */
  231. if ((fnd->funct != ret) && engine_unlocked_init(ret)) {
  232. /* If there was a previous default we release it. */
  233. if (fnd->funct)
  234. engine_unlocked_finish(fnd->funct, 0);
  235. fnd->funct = ret;
  236. #ifdef ENGINE_TABLE_DEBUG
  237. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
  238. "setting default to '%s'\n", f, l, nid, ret->id);
  239. #endif
  240. }
  241. #ifdef ENGINE_TABLE_DEBUG
  242. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
  243. "newly initialised '%s'\n", f, l, nid, ret->id);
  244. #endif
  245. goto end;
  246. }
  247. goto trynext;
  248. end:
  249. /*
  250. * If it failed, it is unlikely to succeed again until some future
  251. * registrations have taken place. In all cases, we cache.
  252. */
  253. if (fnd)
  254. fnd->uptodate = 1;
  255. #ifdef ENGINE_TABLE_DEBUG
  256. if (ret)
  257. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
  258. "ENGINE '%s'\n", f, l, nid, ret->id);
  259. else
  260. fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
  261. "'no matching ENGINE'\n", f, l, nid);
  262. #endif
  263. CRYPTO_THREAD_unlock(global_engine_lock);
  264. /*
  265. * Whatever happened, any failed init()s are not failures in this
  266. * context, so clear our error state.
  267. */
  268. ERR_pop_to_mark();
  269. return ret;
  270. }
  271. /* Table enumeration */
  272. static void int_dall(const ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
  273. {
  274. dall->cb(pile->nid, pile->sk, pile->funct, dall->arg);
  275. }
  276. IMPLEMENT_LHASH_DOALL_ARG_CONST(ENGINE_PILE, ENGINE_PILE_DOALL);
  277. void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
  278. void *arg)
  279. {
  280. ENGINE_PILE_DOALL dall;
  281. dall.cb = cb;
  282. dall.arg = arg;
  283. if (table)
  284. lh_ENGINE_PILE_doall_ENGINE_PILE_DOALL(&table->piles, int_dall, &dall);
  285. }