2
0

eng_list.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright 2001-2021 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. ERR_raise(ERR_LIB_ENGINE, 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. ERR_raise(ERR_LIB_ENGINE, 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. ERR_raise(ERR_LIB_ENGINE, 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. ERR_raise(ERR_LIB_ENGINE, 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_PRINT(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. ERR_raise(ERR_LIB_ENGINE, 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. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST);
  105. return 0;
  106. }
  107. /* un-link e from the chain. */
  108. if (e->next)
  109. e->next->prev = e->prev;
  110. if (e->prev)
  111. e->prev->next = e->next;
  112. /* Correct our head/tail if necessary. */
  113. if (engine_list_head == e)
  114. engine_list_head = e->next;
  115. if (engine_list_tail == e)
  116. engine_list_tail = e->prev;
  117. engine_free_util(e, 0);
  118. return 1;
  119. }
  120. /* Get the first/last "ENGINE" type available. */
  121. ENGINE *ENGINE_get_first(void)
  122. {
  123. ENGINE *ret;
  124. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  125. ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
  126. return NULL;
  127. }
  128. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  129. return NULL;
  130. ret = engine_list_head;
  131. if (ret) {
  132. ret->struct_ref++;
  133. ENGINE_REF_PRINT(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. ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
  143. return NULL;
  144. }
  145. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  146. return NULL;
  147. ret = engine_list_tail;
  148. if (ret) {
  149. ret->struct_ref++;
  150. ENGINE_REF_PRINT(ret, 0, 1);
  151. }
  152. CRYPTO_THREAD_unlock(global_engine_lock);
  153. return ret;
  154. }
  155. /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
  156. ENGINE *ENGINE_get_next(ENGINE *e)
  157. {
  158. ENGINE *ret = NULL;
  159. if (e == NULL) {
  160. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  161. return NULL;
  162. }
  163. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  164. return NULL;
  165. ret = e->next;
  166. if (ret) {
  167. /* Return a valid structural reference to the next ENGINE */
  168. ret->struct_ref++;
  169. ENGINE_REF_PRINT(ret, 0, 1);
  170. }
  171. CRYPTO_THREAD_unlock(global_engine_lock);
  172. /* Release the structural reference to the previous ENGINE */
  173. ENGINE_free(e);
  174. return ret;
  175. }
  176. ENGINE *ENGINE_get_prev(ENGINE *e)
  177. {
  178. ENGINE *ret = NULL;
  179. if (e == NULL) {
  180. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  181. return NULL;
  182. }
  183. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  184. return NULL;
  185. ret = e->prev;
  186. if (ret) {
  187. /* Return a valid structural reference to the next ENGINE */
  188. ret->struct_ref++;
  189. ENGINE_REF_PRINT(ret, 0, 1);
  190. }
  191. CRYPTO_THREAD_unlock(global_engine_lock);
  192. /* Release the structural reference to the previous ENGINE */
  193. ENGINE_free(e);
  194. return ret;
  195. }
  196. /* Add another "ENGINE" type into the list. */
  197. int ENGINE_add(ENGINE *e)
  198. {
  199. int to_return = 1;
  200. if (e == NULL) {
  201. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  202. return 0;
  203. }
  204. if ((e->id == NULL) || (e->name == NULL)) {
  205. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
  206. return 0;
  207. }
  208. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  209. return 0;
  210. if (!engine_list_add(e)) {
  211. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  212. to_return = 0;
  213. }
  214. CRYPTO_THREAD_unlock(global_engine_lock);
  215. return to_return;
  216. }
  217. /* Remove an existing "ENGINE" type from the array. */
  218. int ENGINE_remove(ENGINE *e)
  219. {
  220. int to_return = 1;
  221. if (e == NULL) {
  222. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  223. return 0;
  224. }
  225. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  226. return 0;
  227. if (!engine_list_remove(e)) {
  228. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  229. to_return = 0;
  230. }
  231. CRYPTO_THREAD_unlock(global_engine_lock);
  232. return to_return;
  233. }
  234. static void engine_cpy(ENGINE *dest, const ENGINE *src)
  235. {
  236. dest->id = src->id;
  237. dest->name = src->name;
  238. dest->rsa_meth = src->rsa_meth;
  239. #ifndef OPENSSL_NO_DSA
  240. dest->dsa_meth = src->dsa_meth;
  241. #endif
  242. #ifndef OPENSSL_NO_DH
  243. dest->dh_meth = src->dh_meth;
  244. #endif
  245. #ifndef OPENSSL_NO_EC
  246. dest->ec_meth = src->ec_meth;
  247. #endif
  248. dest->rand_meth = src->rand_meth;
  249. dest->ciphers = src->ciphers;
  250. dest->digests = src->digests;
  251. dest->pkey_meths = src->pkey_meths;
  252. dest->destroy = src->destroy;
  253. dest->init = src->init;
  254. dest->finish = src->finish;
  255. dest->ctrl = src->ctrl;
  256. dest->load_privkey = src->load_privkey;
  257. dest->load_pubkey = src->load_pubkey;
  258. dest->cmd_defns = src->cmd_defns;
  259. dest->flags = src->flags;
  260. }
  261. ENGINE *ENGINE_by_id(const char *id)
  262. {
  263. ENGINE *iterator;
  264. char *load_dir = NULL;
  265. if (id == NULL) {
  266. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  267. return NULL;
  268. }
  269. ENGINE_load_builtin_engines();
  270. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  271. ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
  272. return NULL;
  273. }
  274. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  275. return NULL;
  276. iterator = engine_list_head;
  277. while (iterator && (strcmp(id, iterator->id) != 0))
  278. iterator = iterator->next;
  279. if (iterator != NULL) {
  280. /*
  281. * We need to return a structural reference. If this is an ENGINE
  282. * type that returns copies, make a duplicate - otherwise increment
  283. * the existing ENGINE's reference count.
  284. */
  285. if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
  286. ENGINE *cp = ENGINE_new();
  287. if (cp == NULL)
  288. iterator = NULL;
  289. else {
  290. engine_cpy(cp, iterator);
  291. iterator = cp;
  292. }
  293. } else {
  294. iterator->struct_ref++;
  295. ENGINE_REF_PRINT(iterator, 0, 1);
  296. }
  297. }
  298. CRYPTO_THREAD_unlock(global_engine_lock);
  299. if (iterator != NULL)
  300. return iterator;
  301. /*
  302. * Prevent infinite recursion if we're looking for the dynamic engine.
  303. */
  304. if (strcmp(id, "dynamic")) {
  305. if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
  306. load_dir = ENGINESDIR;
  307. iterator = ENGINE_by_id("dynamic");
  308. if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
  309. !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
  310. !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
  311. load_dir, 0) ||
  312. !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
  313. !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
  314. goto notfound;
  315. return iterator;
  316. }
  317. notfound:
  318. ENGINE_free(iterator);
  319. ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
  320. return NULL;
  321. /* EEK! Experimental code ends */
  322. }
  323. int ENGINE_up_ref(ENGINE *e)
  324. {
  325. int i;
  326. if (e == NULL) {
  327. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  328. return 0;
  329. }
  330. CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
  331. return 1;
  332. }