PageRenderTime 25ms CodeModel.GetById 10ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/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/*
 33 * Principal Author: Brian Wellington
 34 * $Id$
 35 */
 36#ifdef OPENSSL
 37
 38#include <config.h>
 39
 40#include <isc/entropy.h>
 41#include <isc/mem.h>
 42#include <isc/mutex.h>
 43#include <isc/mutexblock.h>
 44#include <isc/string.h>
 45#include <isc/thread.h>
 46#include <isc/util.h>
 47
 48#include <dst/result.h>
 49
 50#include "dst_internal.h"
 51#include "dst_openssl.h"
 52
 53#ifdef USE_ENGINE
 54#include <openssl/engine.h>
 55#endif
 56
 57static RAND_METHOD *rm = NULL;
 58
 59static isc_mutex_t *locks = NULL;
 60static int nlocks;
 61
 62#ifdef USE_ENGINE
 63static ENGINE *e = NULL;
 64#endif
 65
 66static int
 67entropy_get(unsigned char *buf, int num) {
 68	isc_result_t result;
 69	if (num < 0)
 70		return (-1);
 71	result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
 72	return (result == ISC_R_SUCCESS ? 1 : -1);
 73}
 74
 75static int
 76entropy_status(void) {
 77	return (dst__entropy_status() > 32);
 78}
 79
 80static int
 81entropy_getpseudo(unsigned char *buf, int num) {
 82	isc_result_t result;
 83	if (num < 0)
 84		return (-1);
 85	result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
 86	return (result == ISC_R_SUCCESS ? 1 : -1);
 87}
 88
 89static void
 90entropy_add(const void *buf, int num, double entropy) {
 91	/*
 92	 * Do nothing.  The only call to this provides no useful data anyway.
 93	 */
 94	UNUSED(buf);
 95	UNUSED(num);
 96	UNUSED(entropy);
 97}
 98
 99static void
100lock_callback(int mode, int type, const char *file, int line) {
101	UNUSED(file);
102	UNUSED(line);
103	if ((mode & CRYPTO_LOCK) != 0)
104		LOCK(&locks[type]);
105	else
106		UNLOCK(&locks[type]);
107}
108
109static unsigned long
110id_callback(void) {
111	return ((unsigned long)isc_thread_self());
112}
113
114static void *
115mem_alloc(size_t size) {
116#ifdef OPENSSL_LEAKS
117	void *ptr;
118
119	INSIST(dst__memory_pool != NULL);
120	ptr = isc_mem_allocate(dst__memory_pool, size);
121	return (ptr);
122#else
123	INSIST(dst__memory_pool != NULL);
124	return (isc_mem_allocate(dst__memory_pool, size));
125#endif
126}
127
128static void
129mem_free(void *ptr) {
130	INSIST(dst__memory_pool != NULL);
131	if (ptr != NULL)
132		isc_mem_free(dst__memory_pool, ptr);
133}
134
135static void *
136mem_realloc(void *ptr, size_t size) {
137#ifdef OPENSSL_LEAKS
138	void *rptr;
139
140	INSIST(dst__memory_pool != NULL);
141	rptr = isc_mem_reallocate(dst__memory_pool, ptr, size);
142	return (rptr);
143#else
144	INSIST(dst__memory_pool != NULL);
145	return (isc_mem_reallocate(dst__memory_pool, ptr, size));
146#endif
147}
148
149isc_result_t
150dst__openssl_init(const char *engine) {
151	isc_result_t result;
152#ifdef USE_ENGINE
153	ENGINE *re;
154#else
155
156	UNUSED(engine);
157#endif
158
159#ifdef  DNS_CRYPTO_LEAKS
160	CRYPTO_malloc_debug_init();
161	CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
162	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
163#endif
164	CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
165	nlocks = CRYPTO_num_locks();
166	locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
167	if (locks == NULL)
168		return (ISC_R_NOMEMORY);
169	result = isc_mutexblock_init(locks, nlocks);
170	if (result != ISC_R_SUCCESS)
171		goto cleanup_mutexalloc;
172	CRYPTO_set_locking_callback(lock_callback);
173	CRYPTO_set_id_callback(id_callback);
174
175	rm = mem_alloc(sizeof(RAND_METHOD));
176	if (rm == NULL) {
177		result = ISC_R_NOMEMORY;
178		goto cleanup_mutexinit;
179	}
180	rm->seed = NULL;
181	rm->bytes = entropy_get;
182	rm->cleanup = NULL;
183	rm->add = entropy_add;
184	rm->pseudorand = entropy_getpseudo;
185	rm->status = entropy_status;
186
187#ifdef USE_ENGINE
188	OPENSSL_config(NULL);
189
190	if (engine != NULL && *engine == '\0')
191		engine = NULL;
192
193	if (engine != NULL) {
194		e = ENGINE_by_id(engine);
195		if (e == NULL) {
196			result = DST_R_NOENGINE;
197			goto cleanup_rm;
198		}
199		/* This will init the engine. */
200		if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
201			result = DST_R_NOENGINE;
202			goto cleanup_rm;
203		}
204	}
205
206	re = ENGINE_get_default_RAND();
207	if (re == NULL) {
208		re = ENGINE_new();
209		if (re == NULL) {
210			result = ISC_R_NOMEMORY;
211			goto cleanup_rm;
212		}
213		ENGINE_set_RAND(re, rm);
214		ENGINE_set_default_RAND(re);
215		ENGINE_free(re);
216	} else
217		ENGINE_finish(re);
218#else
219	RAND_set_rand_method(rm);
220#endif /* USE_ENGINE */
221	return (ISC_R_SUCCESS);
222
223#ifdef USE_ENGINE
224 cleanup_rm:
225	if (e != NULL)
226		ENGINE_free(e);
227	e = NULL;
228	mem_free(rm);
229	rm = NULL;
230#endif
231 cleanup_mutexinit:
232	CRYPTO_set_locking_callback(NULL);
233	DESTROYMUTEXBLOCK(locks, nlocks);
234 cleanup_mutexalloc:
235	mem_free(locks);
236	locks = NULL;
237	return (result);
238}
239
240void
241dst__openssl_destroy() {
242
243	/*
244	 * Sequence taken from apps_shutdown() in <apps/apps.h>.
245	 */
246	if (rm != NULL) {
247#if OPENSSL_VERSION_NUMBER >= 0x00907000L
248		RAND_cleanup();
249#endif
250		mem_free(rm);
251		rm = NULL;
252	}
253#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
254	CONF_modules_free();
255#endif
256	OBJ_cleanup();
257	EVP_cleanup();
258#if defined(USE_ENGINE)
259	if (e != NULL)
260		ENGINE_free(e);
261	e = NULL;
262#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
263	ENGINE_cleanup();
264#endif
265#endif
266#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
267	CRYPTO_cleanup_all_ex_data();
268#endif
269	ERR_clear_error();
270	ERR_remove_state(0);
271	ERR_free_strings();
272
273#ifdef  DNS_CRYPTO_LEAKS
274	CRYPTO_mem_leaks_fp(stderr);
275#endif
276
277	if (locks != NULL) {
278		CRYPTO_set_locking_callback(NULL);
279		DESTROYMUTEXBLOCK(locks, nlocks);
280		mem_free(locks);
281		locks = NULL;
282	}
283}
284
285isc_result_t
286dst__openssl_toresult(isc_result_t fallback) {
287	isc_result_t result = fallback;
288	int err = ERR_get_error();
289
290	switch (ERR_GET_REASON(err)) {
291	case ERR_R_MALLOC_FAILURE:
292		result = ISC_R_NOMEMORY;
293		break;
294	default:
295		break;
296	}
297	ERR_clear_error();
298	return (result);
299}
300
301#if defined(USE_ENGINE)
302ENGINE *
303dst__openssl_getengine(const char *engine) {
304
305	if (engine == NULL)
306		return (NULL);
307	if (e == NULL)
308		return (NULL);
309	if (strcmp(engine, ENGINE_get_id(e)) == 0)
310		return (e);
311	return (NULL);
312}
313#endif
314
315#else /* OPENSSL */
316
317#include <isc/util.h>
318
319EMPTY_TRANSLATION_UNIT
320
321#endif /* OPENSSL */
322/*! \file */