eng_list.c 14 KB

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