eng_list.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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. * The linked list of currently loaded dynamic engines.
  28. */
  29. static ENGINE *engine_dyn_list_head = NULL;
  30. static ENGINE *engine_dyn_list_tail = NULL;
  31. /*
  32. * This cleanup function is only needed internally. If it should be called,
  33. * we register it with the "engine_cleanup_int()" stack to be called during
  34. * cleanup.
  35. */
  36. static void engine_list_cleanup(void)
  37. {
  38. ENGINE *iterator = engine_list_head;
  39. while (iterator != NULL) {
  40. ENGINE_remove(iterator);
  41. iterator = engine_list_head;
  42. }
  43. return;
  44. }
  45. /*
  46. * These static functions starting with a lower case "engine_" always take
  47. * place when global_engine_lock has been locked up.
  48. */
  49. static int engine_list_add(ENGINE *e)
  50. {
  51. int conflict = 0;
  52. ENGINE *iterator = NULL;
  53. if (e == NULL) {
  54. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  55. return 0;
  56. }
  57. iterator = engine_list_head;
  58. while (iterator && !conflict) {
  59. conflict = (strcmp(iterator->id, e->id) == 0);
  60. iterator = iterator->next;
  61. }
  62. if (conflict) {
  63. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID);
  64. return 0;
  65. }
  66. if (engine_list_head == NULL) {
  67. /* We are adding to an empty list. */
  68. if (engine_list_tail) {
  69. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  70. return 0;
  71. }
  72. engine_list_head = e;
  73. e->prev = NULL;
  74. /*
  75. * The first time the list allocates, we should register the cleanup.
  76. */
  77. engine_cleanup_add_last(engine_list_cleanup);
  78. } else {
  79. /* We are adding to the tail of an existing list. */
  80. if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
  81. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  82. return 0;
  83. }
  84. engine_list_tail->next = e;
  85. e->prev = engine_list_tail;
  86. }
  87. /*
  88. * Having the engine in the list assumes a structural reference.
  89. */
  90. e->struct_ref++;
  91. ENGINE_REF_PRINT(e, 0, 1);
  92. /* However it came to be, e is the last item in the list. */
  93. engine_list_tail = e;
  94. e->next = NULL;
  95. return 1;
  96. }
  97. static int engine_list_remove(ENGINE *e)
  98. {
  99. ENGINE *iterator;
  100. if (e == NULL) {
  101. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  102. return 0;
  103. }
  104. /* We need to check that e is in our linked list! */
  105. iterator = engine_list_head;
  106. while (iterator && (iterator != e))
  107. iterator = iterator->next;
  108. if (iterator == NULL) {
  109. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ENGINE_IS_NOT_IN_LIST);
  110. return 0;
  111. }
  112. /* un-link e from the chain. */
  113. if (e->next)
  114. e->next->prev = e->prev;
  115. if (e->prev)
  116. e->prev->next = e->next;
  117. /* Correct our head/tail if necessary. */
  118. if (engine_list_head == e)
  119. engine_list_head = e->next;
  120. if (engine_list_tail == e)
  121. engine_list_tail = e->prev;
  122. engine_free_util(e, 0);
  123. return 1;
  124. }
  125. /* Add engine to dynamic engine list. */
  126. int engine_add_dynamic_id(ENGINE *e, ENGINE_DYNAMIC_ID dynamic_id,
  127. int not_locked)
  128. {
  129. int result = 0;
  130. ENGINE *iterator = NULL;
  131. if (e == NULL)
  132. return 0;
  133. if (e->dynamic_id == NULL && dynamic_id == NULL)
  134. return 0;
  135. if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
  136. return 0;
  137. if (dynamic_id != NULL) {
  138. iterator = engine_dyn_list_head;
  139. while (iterator != NULL) {
  140. if (iterator->dynamic_id == dynamic_id)
  141. goto err;
  142. iterator = iterator->next;
  143. }
  144. if (e->dynamic_id != NULL)
  145. goto err;
  146. e->dynamic_id = dynamic_id;
  147. }
  148. if (engine_dyn_list_head == NULL) {
  149. /* We are adding to an empty list. */
  150. if (engine_dyn_list_tail != NULL)
  151. goto err;
  152. engine_dyn_list_head = e;
  153. e->prev_dyn = NULL;
  154. } else {
  155. /* We are adding to the tail of an existing list. */
  156. if (engine_dyn_list_tail == NULL
  157. || engine_dyn_list_tail->next_dyn != NULL)
  158. goto err;
  159. engine_dyn_list_tail->next_dyn = e;
  160. e->prev_dyn = engine_dyn_list_tail;
  161. }
  162. engine_dyn_list_tail = e;
  163. e->next_dyn = NULL;
  164. result = 1;
  165. err:
  166. if (not_locked)
  167. CRYPTO_THREAD_unlock(global_engine_lock);
  168. return result;
  169. }
  170. /* Remove engine from dynamic engine list. */
  171. void engine_remove_dynamic_id(ENGINE *e, int not_locked)
  172. {
  173. if (e == NULL || e->dynamic_id == NULL)
  174. return;
  175. if (not_locked && !CRYPTO_THREAD_write_lock(global_engine_lock))
  176. return;
  177. e->dynamic_id = NULL;
  178. /* un-link e from the chain. */
  179. if (e->next_dyn != NULL)
  180. e->next_dyn->prev_dyn = e->prev_dyn;
  181. if (e->prev_dyn != NULL)
  182. e->prev_dyn->next_dyn = e->next_dyn;
  183. /* Correct our head/tail if necessary. */
  184. if (engine_dyn_list_head == e)
  185. engine_dyn_list_head = e->next_dyn;
  186. if (engine_dyn_list_tail == e)
  187. engine_dyn_list_tail = e->prev_dyn;
  188. if (not_locked)
  189. CRYPTO_THREAD_unlock(global_engine_lock);
  190. }
  191. /* Get the first/last "ENGINE" type available. */
  192. ENGINE *ENGINE_get_first(void)
  193. {
  194. ENGINE *ret;
  195. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  196. /* Maybe this should be raised in do_engine_lock_init() */
  197. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  198. return NULL;
  199. }
  200. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  201. return NULL;
  202. ret = engine_list_head;
  203. if (ret) {
  204. ret->struct_ref++;
  205. ENGINE_REF_PRINT(ret, 0, 1);
  206. }
  207. CRYPTO_THREAD_unlock(global_engine_lock);
  208. return ret;
  209. }
  210. ENGINE *ENGINE_get_last(void)
  211. {
  212. ENGINE *ret;
  213. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  214. /* Maybe this should be raised in do_engine_lock_init() */
  215. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  216. return NULL;
  217. }
  218. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  219. return NULL;
  220. ret = engine_list_tail;
  221. if (ret) {
  222. ret->struct_ref++;
  223. ENGINE_REF_PRINT(ret, 0, 1);
  224. }
  225. CRYPTO_THREAD_unlock(global_engine_lock);
  226. return ret;
  227. }
  228. /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
  229. ENGINE *ENGINE_get_next(ENGINE *e)
  230. {
  231. ENGINE *ret = NULL;
  232. if (e == NULL) {
  233. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  234. return NULL;
  235. }
  236. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  237. return NULL;
  238. ret = e->next;
  239. if (ret) {
  240. /* Return a valid structural reference to the next ENGINE */
  241. ret->struct_ref++;
  242. ENGINE_REF_PRINT(ret, 0, 1);
  243. }
  244. CRYPTO_THREAD_unlock(global_engine_lock);
  245. /* Release the structural reference to the previous ENGINE */
  246. ENGINE_free(e);
  247. return ret;
  248. }
  249. ENGINE *ENGINE_get_prev(ENGINE *e)
  250. {
  251. ENGINE *ret = NULL;
  252. if (e == NULL) {
  253. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  254. return NULL;
  255. }
  256. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  257. return NULL;
  258. ret = e->prev;
  259. if (ret) {
  260. /* Return a valid structural reference to the next ENGINE */
  261. ret->struct_ref++;
  262. ENGINE_REF_PRINT(ret, 0, 1);
  263. }
  264. CRYPTO_THREAD_unlock(global_engine_lock);
  265. /* Release the structural reference to the previous ENGINE */
  266. ENGINE_free(e);
  267. return ret;
  268. }
  269. /* Add another "ENGINE" type into the list. */
  270. int ENGINE_add(ENGINE *e)
  271. {
  272. int to_return = 1;
  273. if (e == NULL) {
  274. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  275. return 0;
  276. }
  277. if ((e->id == NULL) || (e->name == NULL)) {
  278. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
  279. return 0;
  280. }
  281. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  282. return 0;
  283. if (!engine_list_add(e)) {
  284. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  285. to_return = 0;
  286. }
  287. CRYPTO_THREAD_unlock(global_engine_lock);
  288. return to_return;
  289. }
  290. /* Remove an existing "ENGINE" type from the array. */
  291. int ENGINE_remove(ENGINE *e)
  292. {
  293. int to_return = 1;
  294. if (e == NULL) {
  295. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  296. return 0;
  297. }
  298. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  299. return 0;
  300. if (!engine_list_remove(e)) {
  301. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  302. to_return = 0;
  303. }
  304. CRYPTO_THREAD_unlock(global_engine_lock);
  305. return to_return;
  306. }
  307. static void engine_cpy(ENGINE *dest, const ENGINE *src)
  308. {
  309. dest->id = src->id;
  310. dest->name = src->name;
  311. dest->rsa_meth = src->rsa_meth;
  312. #ifndef OPENSSL_NO_DSA
  313. dest->dsa_meth = src->dsa_meth;
  314. #endif
  315. #ifndef OPENSSL_NO_DH
  316. dest->dh_meth = src->dh_meth;
  317. #endif
  318. #ifndef OPENSSL_NO_EC
  319. dest->ec_meth = src->ec_meth;
  320. #endif
  321. dest->rand_meth = src->rand_meth;
  322. dest->ciphers = src->ciphers;
  323. dest->digests = src->digests;
  324. dest->pkey_meths = src->pkey_meths;
  325. dest->destroy = src->destroy;
  326. dest->init = src->init;
  327. dest->finish = src->finish;
  328. dest->ctrl = src->ctrl;
  329. dest->load_privkey = src->load_privkey;
  330. dest->load_pubkey = src->load_pubkey;
  331. dest->cmd_defns = src->cmd_defns;
  332. dest->flags = src->flags;
  333. dest->dynamic_id = src->dynamic_id;
  334. engine_add_dynamic_id(dest, NULL, 0);
  335. }
  336. ENGINE *ENGINE_by_id(const char *id)
  337. {
  338. ENGINE *iterator;
  339. char *load_dir = NULL;
  340. if (id == NULL) {
  341. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  342. return NULL;
  343. }
  344. ENGINE_load_builtin_engines();
  345. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  346. /* Maybe this should be raised in do_engine_lock_init() */
  347. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  348. return NULL;
  349. }
  350. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  351. return NULL;
  352. iterator = engine_list_head;
  353. while (iterator && (strcmp(id, iterator->id) != 0))
  354. iterator = iterator->next;
  355. if (iterator != NULL) {
  356. /*
  357. * We need to return a structural reference. If this is an ENGINE
  358. * type that returns copies, make a duplicate - otherwise increment
  359. * the existing ENGINE's reference count.
  360. */
  361. if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
  362. ENGINE *cp = ENGINE_new();
  363. if (cp == NULL)
  364. iterator = NULL;
  365. else {
  366. engine_cpy(cp, iterator);
  367. iterator = cp;
  368. }
  369. } else {
  370. iterator->struct_ref++;
  371. ENGINE_REF_PRINT(iterator, 0, 1);
  372. }
  373. }
  374. CRYPTO_THREAD_unlock(global_engine_lock);
  375. if (iterator != NULL)
  376. return iterator;
  377. /*
  378. * Prevent infinite recursion if we're looking for the dynamic engine.
  379. */
  380. if (strcmp(id, "dynamic")) {
  381. if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
  382. load_dir = ENGINESDIR;
  383. iterator = ENGINE_by_id("dynamic");
  384. if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
  385. !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
  386. !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
  387. load_dir, 0) ||
  388. !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
  389. !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
  390. goto notfound;
  391. return iterator;
  392. }
  393. notfound:
  394. ENGINE_free(iterator);
  395. ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
  396. return NULL;
  397. /* EEK! Experimental code ends */
  398. }
  399. int ENGINE_up_ref(ENGINE *e)
  400. {
  401. int i;
  402. if (e == NULL) {
  403. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  404. return 0;
  405. }
  406. CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock);
  407. return 1;
  408. }