eng_list.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  4. *
  5. * Licensed under the Apache License 2.0 (the "License"). You may not use
  6. * this file except in compliance with the License. You can obtain a copy
  7. * in the file LICENSE in the source distribution or at
  8. * https://www.openssl.org/source/license.html
  9. */
  10. /* We need to use some engine deprecated APIs */
  11. #define OPENSSL_SUPPRESS_DEPRECATED
  12. #include "eng_local.h"
  13. /*
  14. * The linked-list of pointers to engine types. engine_list_head incorporates
  15. * an implicit structural reference but engine_list_tail does not - the
  16. * latter is a computational optimization and only points to something that
  17. * is already pointed to by its predecessor in the list (or engine_list_head
  18. * itself). In the same way, the use of the "prev" pointer in each ENGINE is
  19. * to save excessive list iteration, it doesn't correspond to an extra
  20. * structural reference. Hence, engine_list_head, and each non-null "next"
  21. * pointer account for the list itself assuming exactly 1 structural
  22. * reference on each list member.
  23. */
  24. static ENGINE *engine_list_head = NULL;
  25. static ENGINE *engine_list_tail = NULL;
  26. /*
  27. * This cleanup function is only needed internally. If it should be called,
  28. * we register it with the "engine_cleanup_int()" stack to be called during
  29. * cleanup.
  30. */
  31. static void engine_list_cleanup(void)
  32. {
  33. ENGINE *iterator = engine_list_head;
  34. while (iterator != NULL) {
  35. ENGINE_remove(iterator);
  36. iterator = engine_list_head;
  37. }
  38. return;
  39. }
  40. /*
  41. * These static functions starting with a lower case "engine_" always take
  42. * place when global_engine_lock has been locked up.
  43. */
  44. static int engine_list_add(ENGINE *e)
  45. {
  46. int conflict = 0;
  47. ENGINE *iterator = NULL;
  48. if (e == NULL) {
  49. ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER);
  50. return 0;
  51. }
  52. iterator = engine_list_head;
  53. while (iterator && !conflict) {
  54. conflict = (strcmp(iterator->id, e->id) == 0);
  55. iterator = iterator->next;
  56. }
  57. if (conflict) {
  58. ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID);
  59. return 0;
  60. }
  61. if (engine_list_head == NULL) {
  62. /* We are adding to an empty list. */
  63. if (engine_list_tail) {
  64. ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
  65. return 0;
  66. }
  67. engine_list_head = e;
  68. e->prev = NULL;
  69. /*
  70. * The first time the list allocates, we should register the cleanup.
  71. */
  72. engine_cleanup_add_last(engine_list_cleanup);
  73. } else {
  74. /* We are adding to the tail of an existing list. */
  75. if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
  76. ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
  77. return 0;
  78. }
  79. engine_list_tail->next = e;
  80. e->prev = engine_list_tail;
  81. }
  82. /*
  83. * Having the engine in the list assumes a structural reference.
  84. */
  85. e->struct_ref++;
  86. engine_ref_debug(e, 0, 1);
  87. /* However it came to be, e is the last item in the list. */
  88. engine_list_tail = e;
  89. e->next = NULL;
  90. return 1;
  91. }
  92. static int engine_list_remove(ENGINE *e)
  93. {
  94. ENGINE *iterator;
  95. if (e == NULL) {
  96. ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
  97. return 0;
  98. }
  99. /* We need to check that e is in our linked list! */
  100. iterator = engine_list_head;
  101. while (iterator && (iterator != e))
  102. iterator = iterator->next;
  103. if (iterator == NULL) {
  104. ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
  105. ENGINE_R_ENGINE_IS_NOT_IN_LIST);
  106. return 0;
  107. }
  108. /* un-link e from the chain. */
  109. if (e->next)
  110. e->next->prev = e->prev;
  111. if (e->prev)
  112. e->prev->next = e->next;
  113. /* Correct our head/tail if necessary. */
  114. if (engine_list_head == e)
  115. engine_list_head = e->next;
  116. if (engine_list_tail == e)
  117. engine_list_tail = e->prev;
  118. engine_free_util(e, 0);
  119. return 1;
  120. }
  121. /* Get the first/last "ENGINE" type available. */
  122. ENGINE *ENGINE_get_first(void)
  123. {
  124. ENGINE *ret;
  125. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  126. ENGINEerr(ENGINE_F_ENGINE_GET_FIRST, ERR_R_MALLOC_FAILURE);
  127. return NULL;
  128. }
  129. CRYPTO_THREAD_write_lock(global_engine_lock);
  130. ret = engine_list_head;
  131. if (ret) {
  132. ret->struct_ref++;
  133. engine_ref_debug(ret, 0, 1);
  134. }
  135. CRYPTO_THREAD_unlock(global_engine_lock);
  136. return ret;
  137. }
  138. ENGINE *ENGINE_get_last(void)
  139. {
  140. ENGINE *ret;
  141. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  142. ENGINEerr(ENGINE_F_ENGINE_GET_LAST, ERR_R_MALLOC_FAILURE);
  143. return NULL;
  144. }
  145. CRYPTO_THREAD_write_lock(global_engine_lock);
  146. ret = engine_list_tail;
  147. if (ret) {
  148. ret->struct_ref++;
  149. engine_ref_debug(ret, 0, 1);
  150. }
  151. CRYPTO_THREAD_unlock(global_engine_lock);
  152. return ret;
  153. }
  154. /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
  155. ENGINE *ENGINE_get_next(ENGINE *e)
  156. {
  157. ENGINE *ret = NULL;
  158. if (e == NULL) {
  159. ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, ERR_R_PASSED_NULL_PARAMETER);
  160. return 0;
  161. }
  162. CRYPTO_THREAD_write_lock(global_engine_lock);
  163. ret = e->next;
  164. if (ret) {
  165. /* Return a valid structural reference to the next ENGINE */
  166. ret->struct_ref++;
  167. engine_ref_debug(ret, 0, 1);
  168. }
  169. CRYPTO_THREAD_unlock(global_engine_lock);
  170. /* Release the structural reference to the previous ENGINE */
  171. ENGINE_free(e);
  172. return ret;
  173. }
  174. ENGINE *ENGINE_get_prev(ENGINE *e)
  175. {
  176. ENGINE *ret = NULL;
  177. if (e == NULL) {
  178. ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER);
  179. return 0;
  180. }
  181. CRYPTO_THREAD_write_lock(global_engine_lock);
  182. ret = e->prev;
  183. if (ret) {
  184. /* Return a valid structural reference to the next ENGINE */
  185. ret->struct_ref++;
  186. engine_ref_debug(ret, 0, 1);
  187. }
  188. CRYPTO_THREAD_unlock(global_engine_lock);
  189. /* Release the structural reference to the previous ENGINE */
  190. ENGINE_free(e);
  191. return ret;
  192. }
  193. /* Add another "ENGINE" type into the list. */
  194. int ENGINE_add(ENGINE *e)
  195. {
  196. int to_return = 1;
  197. if (e == NULL) {
  198. ENGINEerr(ENGINE_F_ENGINE_ADD, ERR_R_PASSED_NULL_PARAMETER);
  199. return 0;
  200. }
  201. if ((e->id == NULL) || (e->name == NULL)) {
  202. ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING);
  203. return 0;
  204. }
  205. CRYPTO_THREAD_write_lock(global_engine_lock);
  206. if (!engine_list_add(e)) {
  207. ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
  208. to_return = 0;
  209. }
  210. CRYPTO_THREAD_unlock(global_engine_lock);
  211. return to_return;
  212. }
  213. /* Remove an existing "ENGINE" type from the array. */
  214. int ENGINE_remove(ENGINE *e)
  215. {
  216. int to_return = 1;
  217. if (e == NULL) {
  218. ENGINEerr(ENGINE_F_ENGINE_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
  219. return 0;
  220. }
  221. CRYPTO_THREAD_write_lock(global_engine_lock);
  222. if (!engine_list_remove(e)) {
  223. ENGINEerr(ENGINE_F_ENGINE_REMOVE, ENGINE_R_INTERNAL_LIST_ERROR);
  224. to_return = 0;
  225. }
  226. CRYPTO_THREAD_unlock(global_engine_lock);
  227. return to_return;
  228. }
  229. static void engine_cpy(ENGINE *dest, const ENGINE *src)
  230. {
  231. dest->id = src->id;
  232. dest->name = src->name;
  233. #ifndef OPENSSL_NO_RSA
  234. dest->rsa_meth = src->rsa_meth;
  235. #endif
  236. #ifndef OPENSSL_NO_DSA
  237. dest->dsa_meth = src->dsa_meth;
  238. #endif
  239. #ifndef OPENSSL_NO_DH
  240. dest->dh_meth = src->dh_meth;
  241. #endif
  242. #ifndef OPENSSL_NO_EC
  243. dest->ec_meth = src->ec_meth;
  244. #endif
  245. dest->rand_meth = src->rand_meth;
  246. dest->ciphers = src->ciphers;
  247. dest->digests = src->digests;
  248. dest->pkey_meths = src->pkey_meths;
  249. dest->destroy = src->destroy;
  250. dest->init = src->init;
  251. dest->finish = src->finish;
  252. dest->ctrl = src->ctrl;
  253. dest->load_privkey = src->load_privkey;
  254. dest->load_pubkey = src->load_pubkey;
  255. dest->cmd_defns = src->cmd_defns;
  256. dest->flags = src->flags;
  257. }
  258. ENGINE *ENGINE_by_id(const char *id)
  259. {
  260. ENGINE *iterator;
  261. char *load_dir = NULL;
  262. if (id == NULL) {
  263. ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
  264. return NULL;
  265. }
  266. ENGINE_load_builtin_engines();
  267. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  268. ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE);
  269. return NULL;
  270. }
  271. CRYPTO_THREAD_write_lock(global_engine_lock);
  272. iterator = engine_list_head;
  273. while (iterator && (strcmp(id, iterator->id) != 0))
  274. iterator = iterator->next;
  275. if (iterator != NULL) {
  276. /*
  277. * We need to return a structural reference. If this is an ENGINE
  278. * type that returns copies, make a duplicate - otherwise increment
  279. * the existing ENGINE's reference count.
  280. */
  281. if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
  282. ENGINE *cp = ENGINE_new();
  283. if (cp == NULL)
  284. iterator = NULL;
  285. else {
  286. engine_cpy(cp, iterator);
  287. iterator = cp;
  288. }
  289. } else {
  290. iterator->struct_ref++;
  291. engine_ref_debug(iterator, 0, 1);
  292. }
  293. }
  294. CRYPTO_THREAD_unlock(global_engine_lock);
  295. if (iterator != NULL)
  296. return iterator;
  297. /*
  298. * Prevent infinite recursion if we're looking for the dynamic engine.
  299. */
  300. if (strcmp(id, "dynamic")) {
  301. if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
  302. load_dir = ENGINESDIR;
  303. iterator = ENGINE_by_id("dynamic");
  304. if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
  305. !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
  306. !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
  307. load_dir, 0) ||
  308. !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
  309. !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
  310. goto notfound;
  311. return iterator;
  312. }
  313. notfound:
  314. ENGINE_free(iterator);
  315. ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
  316. ERR_add_error_data(2, "id=", id);
  317. return NULL;
  318. /* EEK! Experimental code ends */
  319. }
  320. int ENGINE_up_ref(ENGINE *e)
  321. {
  322. int i;
  323. if (e == NULL) {
  324. ENGINEerr(ENGINE_F_ENGINE_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
  325. return 0;
  326. }
  327. CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
  328. return 1;
  329. }