eng_list.c 10 KB

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