/contrib/bind9/lib/dns/openssl_link.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 322 lines · 239 code · 41 blank · 42 comment · 48 complexity · e6741d900c5133a427f29cd1af54f331 MD5 · raw file

  1. /*
  2. * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Portions Copyright (C) 1999-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  10. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
  12. * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  15. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. *
  17. * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
  18. *
  19. * Permission to use, copy, modify, and/or distribute this software for any
  20. * purpose with or without fee is hereby granted, provided that the above
  21. * copyright notice and this permission notice appear in all copies.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  24. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
  26. * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  27. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  28. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  29. * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30. */
  31. /*
  32. * Principal Author: Brian Wellington
  33. * $Id$
  34. */
  35. #ifdef OPENSSL
  36. #include <config.h>
  37. #include <isc/entropy.h>
  38. #include <isc/mem.h>
  39. #include <isc/mutex.h>
  40. #include <isc/mutexblock.h>
  41. #include <isc/string.h>
  42. #include <isc/thread.h>
  43. #include <isc/util.h>
  44. #include <dst/result.h>
  45. #include "dst_internal.h"
  46. #include "dst_openssl.h"
  47. #ifdef USE_ENGINE
  48. #include <openssl/engine.h>
  49. #endif
  50. static RAND_METHOD *rm = NULL;
  51. static isc_mutex_t *locks = NULL;
  52. static int nlocks;
  53. #ifdef USE_ENGINE
  54. static ENGINE *e = NULL;
  55. #endif
  56. static int
  57. entropy_get(unsigned char *buf, int num) {
  58. isc_result_t result;
  59. if (num < 0)
  60. return (-1);
  61. result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
  62. return (result == ISC_R_SUCCESS ? 1 : -1);
  63. }
  64. static int
  65. entropy_status(void) {
  66. return (dst__entropy_status() > 32);
  67. }
  68. static int
  69. entropy_getpseudo(unsigned char *buf, int num) {
  70. isc_result_t result;
  71. if (num < 0)
  72. return (-1);
  73. result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
  74. return (result == ISC_R_SUCCESS ? 1 : -1);
  75. }
  76. static void
  77. entropy_add(const void *buf, int num, double entropy) {
  78. /*
  79. * Do nothing. The only call to this provides no useful data anyway.
  80. */
  81. UNUSED(buf);
  82. UNUSED(num);
  83. UNUSED(entropy);
  84. }
  85. static void
  86. lock_callback(int mode, int type, const char *file, int line) {
  87. UNUSED(file);
  88. UNUSED(line);
  89. if ((mode & CRYPTO_LOCK) != 0)
  90. LOCK(&locks[type]);
  91. else
  92. UNLOCK(&locks[type]);
  93. }
  94. static unsigned long
  95. id_callback(void) {
  96. return ((unsigned long)isc_thread_self());
  97. }
  98. static void *
  99. mem_alloc(size_t size) {
  100. #ifdef OPENSSL_LEAKS
  101. void *ptr;
  102. INSIST(dst__memory_pool != NULL);
  103. ptr = isc_mem_allocate(dst__memory_pool, size);
  104. return (ptr);
  105. #else
  106. INSIST(dst__memory_pool != NULL);
  107. return (isc_mem_allocate(dst__memory_pool, size));
  108. #endif
  109. }
  110. static void
  111. mem_free(void *ptr) {
  112. INSIST(dst__memory_pool != NULL);
  113. if (ptr != NULL)
  114. isc_mem_free(dst__memory_pool, ptr);
  115. }
  116. static void *
  117. mem_realloc(void *ptr, size_t size) {
  118. #ifdef OPENSSL_LEAKS
  119. void *rptr;
  120. INSIST(dst__memory_pool != NULL);
  121. rptr = isc_mem_reallocate(dst__memory_pool, ptr, size);
  122. return (rptr);
  123. #else
  124. INSIST(dst__memory_pool != NULL);
  125. return (isc_mem_reallocate(dst__memory_pool, ptr, size));
  126. #endif
  127. }
  128. isc_result_t
  129. dst__openssl_init(const char *engine) {
  130. isc_result_t result;
  131. #ifdef USE_ENGINE
  132. ENGINE *re;
  133. #else
  134. UNUSED(engine);
  135. #endif
  136. #ifdef DNS_CRYPTO_LEAKS
  137. CRYPTO_malloc_debug_init();
  138. CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
  139. CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
  140. #endif
  141. CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
  142. nlocks = CRYPTO_num_locks();
  143. locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
  144. if (locks == NULL)
  145. return (ISC_R_NOMEMORY);
  146. result = isc_mutexblock_init(locks, nlocks);
  147. if (result != ISC_R_SUCCESS)
  148. goto cleanup_mutexalloc;
  149. CRYPTO_set_locking_callback(lock_callback);
  150. CRYPTO_set_id_callback(id_callback);
  151. rm = mem_alloc(sizeof(RAND_METHOD));
  152. if (rm == NULL) {
  153. result = ISC_R_NOMEMORY;
  154. goto cleanup_mutexinit;
  155. }
  156. rm->seed = NULL;
  157. rm->bytes = entropy_get;
  158. rm->cleanup = NULL;
  159. rm->add = entropy_add;
  160. rm->pseudorand = entropy_getpseudo;
  161. rm->status = entropy_status;
  162. #ifdef USE_ENGINE
  163. OPENSSL_config(NULL);
  164. if (engine != NULL && *engine == '\0')
  165. engine = NULL;
  166. if (engine != NULL) {
  167. e = ENGINE_by_id(engine);
  168. if (e == NULL) {
  169. result = DST_R_NOENGINE;
  170. goto cleanup_rm;
  171. }
  172. /* This will init the engine. */
  173. if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
  174. result = DST_R_NOENGINE;
  175. goto cleanup_rm;
  176. }
  177. }
  178. re = ENGINE_get_default_RAND();
  179. if (re == NULL) {
  180. re = ENGINE_new();
  181. if (re == NULL) {
  182. result = ISC_R_NOMEMORY;
  183. goto cleanup_rm;
  184. }
  185. ENGINE_set_RAND(re, rm);
  186. ENGINE_set_default_RAND(re);
  187. ENGINE_free(re);
  188. } else
  189. ENGINE_finish(re);
  190. #else
  191. RAND_set_rand_method(rm);
  192. #endif /* USE_ENGINE */
  193. return (ISC_R_SUCCESS);
  194. #ifdef USE_ENGINE
  195. cleanup_rm:
  196. if (e != NULL)
  197. ENGINE_free(e);
  198. e = NULL;
  199. mem_free(rm);
  200. rm = NULL;
  201. #endif
  202. cleanup_mutexinit:
  203. CRYPTO_set_locking_callback(NULL);
  204. DESTROYMUTEXBLOCK(locks, nlocks);
  205. cleanup_mutexalloc:
  206. mem_free(locks);
  207. locks = NULL;
  208. return (result);
  209. }
  210. void
  211. dst__openssl_destroy() {
  212. /*
  213. * Sequence taken from apps_shutdown() in <apps/apps.h>.
  214. */
  215. if (rm != NULL) {
  216. #if OPENSSL_VERSION_NUMBER >= 0x00907000L
  217. RAND_cleanup();
  218. #endif
  219. mem_free(rm);
  220. rm = NULL;
  221. }
  222. #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
  223. CONF_modules_free();
  224. #endif
  225. OBJ_cleanup();
  226. EVP_cleanup();
  227. #if defined(USE_ENGINE)
  228. if (e != NULL)
  229. ENGINE_free(e);
  230. e = NULL;
  231. #if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
  232. ENGINE_cleanup();
  233. #endif
  234. #endif
  235. #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
  236. CRYPTO_cleanup_all_ex_data();
  237. #endif
  238. ERR_clear_error();
  239. ERR_remove_state(0);
  240. ERR_free_strings();
  241. #ifdef DNS_CRYPTO_LEAKS
  242. CRYPTO_mem_leaks_fp(stderr);
  243. #endif
  244. if (locks != NULL) {
  245. CRYPTO_set_locking_callback(NULL);
  246. DESTROYMUTEXBLOCK(locks, nlocks);
  247. mem_free(locks);
  248. locks = NULL;
  249. }
  250. }
  251. isc_result_t
  252. dst__openssl_toresult(isc_result_t fallback) {
  253. isc_result_t result = fallback;
  254. int err = ERR_get_error();
  255. switch (ERR_GET_REASON(err)) {
  256. case ERR_R_MALLOC_FAILURE:
  257. result = ISC_R_NOMEMORY;
  258. break;
  259. default:
  260. break;
  261. }
  262. ERR_clear_error();
  263. return (result);
  264. }
  265. #if defined(USE_ENGINE)
  266. ENGINE *
  267. dst__openssl_getengine(const char *engine) {
  268. if (engine == NULL)
  269. return (NULL);
  270. if (e == NULL)
  271. return (NULL);
  272. if (strcmp(engine, ENGINE_get_id(e)) == 0)
  273. return (e);
  274. return (NULL);
  275. }
  276. #endif
  277. #else /* OPENSSL */
  278. #include <isc/util.h>
  279. EMPTY_TRANSLATION_UNIT
  280. #endif /* OPENSSL */
  281. /*! \file */