eng_list.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. * Copyright 2001-2023 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. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  217. return NULL;
  218. }
  219. ENGINE_REF_PRINT(ret, 0, 1);
  220. }
  221. CRYPTO_THREAD_unlock(global_engine_lock);
  222. return ret;
  223. }
  224. ENGINE *ENGINE_get_last(void)
  225. {
  226. ENGINE *ret;
  227. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  228. /* Maybe this should be raised in do_engine_lock_init() */
  229. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  230. return NULL;
  231. }
  232. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  233. return NULL;
  234. ret = engine_list_tail;
  235. if (ret) {
  236. int ref;
  237. if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) {
  238. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  239. return NULL;
  240. }
  241. ENGINE_REF_PRINT(ret, 0, 1);
  242. }
  243. CRYPTO_THREAD_unlock(global_engine_lock);
  244. return ret;
  245. }
  246. /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
  247. ENGINE *ENGINE_get_next(ENGINE *e)
  248. {
  249. ENGINE *ret = NULL;
  250. if (e == NULL) {
  251. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  252. return NULL;
  253. }
  254. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  255. return NULL;
  256. ret = e->next;
  257. if (ret) {
  258. int ref;
  259. /* Return a valid structural reference to the next ENGINE */
  260. if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) {
  261. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  262. return NULL;
  263. }
  264. ENGINE_REF_PRINT(ret, 0, 1);
  265. }
  266. CRYPTO_THREAD_unlock(global_engine_lock);
  267. /* Release the structural reference to the previous ENGINE */
  268. ENGINE_free(e);
  269. return ret;
  270. }
  271. ENGINE *ENGINE_get_prev(ENGINE *e)
  272. {
  273. ENGINE *ret = NULL;
  274. if (e == NULL) {
  275. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  276. return NULL;
  277. }
  278. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  279. return NULL;
  280. ret = e->prev;
  281. if (ret) {
  282. int ref;
  283. /* Return a valid structural reference to the next ENGINE */
  284. if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) {
  285. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  286. return NULL;
  287. }
  288. ENGINE_REF_PRINT(ret, 0, 1);
  289. }
  290. CRYPTO_THREAD_unlock(global_engine_lock);
  291. /* Release the structural reference to the previous ENGINE */
  292. ENGINE_free(e);
  293. return ret;
  294. }
  295. /* Add another "ENGINE" type into the list. */
  296. int ENGINE_add(ENGINE *e)
  297. {
  298. int to_return = 1;
  299. if (e == NULL) {
  300. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  301. return 0;
  302. }
  303. if ((e->id == NULL) || (e->name == NULL)) {
  304. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
  305. return 0;
  306. }
  307. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  308. return 0;
  309. if (!engine_list_add(e)) {
  310. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  311. to_return = 0;
  312. }
  313. CRYPTO_THREAD_unlock(global_engine_lock);
  314. return to_return;
  315. }
  316. /* Remove an existing "ENGINE" type from the array. */
  317. int ENGINE_remove(ENGINE *e)
  318. {
  319. int to_return = 1;
  320. if (e == NULL) {
  321. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  322. return 0;
  323. }
  324. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  325. return 0;
  326. if (!engine_list_remove(e)) {
  327. ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
  328. to_return = 0;
  329. }
  330. CRYPTO_THREAD_unlock(global_engine_lock);
  331. return to_return;
  332. }
  333. static void engine_cpy(ENGINE *dest, const ENGINE *src)
  334. {
  335. dest->id = src->id;
  336. dest->name = src->name;
  337. dest->rsa_meth = src->rsa_meth;
  338. #ifndef OPENSSL_NO_DSA
  339. dest->dsa_meth = src->dsa_meth;
  340. #endif
  341. #ifndef OPENSSL_NO_DH
  342. dest->dh_meth = src->dh_meth;
  343. #endif
  344. #ifndef OPENSSL_NO_EC
  345. dest->ec_meth = src->ec_meth;
  346. #endif
  347. dest->rand_meth = src->rand_meth;
  348. dest->ciphers = src->ciphers;
  349. dest->digests = src->digests;
  350. dest->pkey_meths = src->pkey_meths;
  351. dest->destroy = src->destroy;
  352. dest->init = src->init;
  353. dest->finish = src->finish;
  354. dest->ctrl = src->ctrl;
  355. dest->load_privkey = src->load_privkey;
  356. dest->load_pubkey = src->load_pubkey;
  357. dest->cmd_defns = src->cmd_defns;
  358. dest->flags = src->flags;
  359. dest->dynamic_id = src->dynamic_id;
  360. engine_add_dynamic_id(dest, NULL, 0);
  361. }
  362. ENGINE *ENGINE_by_id(const char *id)
  363. {
  364. ENGINE *iterator;
  365. char *load_dir = NULL;
  366. if (id == NULL) {
  367. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  368. return NULL;
  369. }
  370. ENGINE_load_builtin_engines();
  371. if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
  372. /* Maybe this should be raised in do_engine_lock_init() */
  373. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  374. return NULL;
  375. }
  376. if (!CRYPTO_THREAD_write_lock(global_engine_lock))
  377. return NULL;
  378. iterator = engine_list_head;
  379. while (iterator && (strcmp(id, iterator->id) != 0))
  380. iterator = iterator->next;
  381. if (iterator != NULL) {
  382. /*
  383. * We need to return a structural reference. If this is an ENGINE
  384. * type that returns copies, make a duplicate - otherwise increment
  385. * the existing ENGINE's reference count.
  386. */
  387. if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
  388. ENGINE *cp = ENGINE_new();
  389. if (cp == NULL)
  390. iterator = NULL;
  391. else {
  392. engine_cpy(cp, iterator);
  393. iterator = cp;
  394. }
  395. } else {
  396. int ref;
  397. if (!CRYPTO_UP_REF(&iterator->struct_ref, &ref)) {
  398. CRYPTO_THREAD_unlock(global_engine_lock);
  399. ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB);
  400. return NULL;
  401. }
  402. ENGINE_REF_PRINT(iterator, 0, 1);
  403. }
  404. }
  405. CRYPTO_THREAD_unlock(global_engine_lock);
  406. if (iterator != NULL)
  407. return iterator;
  408. /*
  409. * Prevent infinite recursion if we're looking for the dynamic engine.
  410. */
  411. if (strcmp(id, "dynamic")) {
  412. if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL)
  413. load_dir = ENGINESDIR;
  414. iterator = ENGINE_by_id("dynamic");
  415. if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
  416. !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
  417. !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
  418. load_dir, 0) ||
  419. !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
  420. !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
  421. goto notfound;
  422. return iterator;
  423. }
  424. notfound:
  425. ENGINE_free(iterator);
  426. ERR_raise_data(ERR_LIB_ENGINE, ENGINE_R_NO_SUCH_ENGINE, "id=%s", id);
  427. return NULL;
  428. /* EEK! Experimental code ends */
  429. }
  430. int ENGINE_up_ref(ENGINE *e)
  431. {
  432. int i;
  433. if (e == NULL) {
  434. ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
  435. return 0;
  436. }
  437. CRYPTO_UP_REF(&e->struct_ref, &i);
  438. return 1;
  439. }