openssl_link.c 7.13 KB
Newer Older
1
/*
Tinderbox User's avatar
Tinderbox User committed
2
 * Portions Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Portions Copyright (C) 1999-2003  Internet Software Consortium.
Automatic Updater's avatar
Automatic Updater committed
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
17
 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
18
 *
Automatic Updater's avatar
Automatic Updater committed
19
 * Permission to use, copy, modify, and/or distribute this software for any
20 21
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
22
 *
Mark Andrews's avatar
Mark Andrews committed
23 24 25 26 27 28 29
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 31 32 33
 */

/*
 * Principal Author: Brian Wellington
Mark Andrews's avatar
Mark Andrews committed
34
 * $Id$
35
 */
36
#ifdef OPENSSL
37 38 39

#include <config.h>

Brian Wellington's avatar
Brian Wellington committed
40
#include <isc/entropy.h>
41
#include <isc/mem.h>
42 43
#include <isc/mutex.h>
#include <isc/mutexblock.h>
44
#include <isc/string.h>
45
#include <isc/thread.h>
Bob Halley's avatar
Bob Halley committed
46
#include <isc/util.h>
47

Francis Dupont's avatar
Francis Dupont committed
48 49
#include <dst/result.h>

50
#include "dst_internal.h"
51
#include "dst_openssl.h"
52

53
#ifdef USE_ENGINE
54 55
#include <openssl/engine.h>
#endif
56

57
static RAND_METHOD *rm = NULL;
58

59 60
static isc_mutex_t *locks = NULL;
static int nlocks;
61

62
#ifdef USE_ENGINE
Francis Dupont's avatar
Francis Dupont committed
63
static ENGINE *e = NULL;
64 65
#endif

Brian Wellington's avatar
Brian Wellington committed
66 67 68 69 70
static int
entropy_get(unsigned char *buf, int num) {
	isc_result_t result;
	if (num < 0)
		return (-1);
71
	result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
72
	return (result == ISC_R_SUCCESS ? 1 : -1);
73 74
}

75 76 77 78 79
static int
entropy_status(void) {
	return (dst__entropy_status() > 32);
}

80 81 82 83 84 85
static int
entropy_getpseudo(unsigned char *buf, int num) {
	isc_result_t result;
	if (num < 0)
		return (-1);
	result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
86
	return (result == ISC_R_SUCCESS ? 1 : -1);
Brian Wellington's avatar
Brian Wellington committed
87 88 89 90 91 92 93 94 95 96 97 98
}

static void
entropy_add(const void *buf, int num, double entropy) {
	/*
	 * Do nothing.  The only call to this provides no useful data anyway.
	 */
	UNUSED(buf);
	UNUSED(num);
	UNUSED(entropy);
}

99 100
static void
lock_callback(int mode, int type, const char *file, int line) {
101 102
	UNUSED(file);
	UNUSED(line);
103 104 105 106 107 108 109 110 111 112 113
	if ((mode & CRYPTO_LOCK) != 0)
		LOCK(&locks[type]);
	else
		UNLOCK(&locks[type]);
}

static unsigned long
id_callback(void) {
	return ((unsigned long)isc_thread_self());
}

114 115
static void *
mem_alloc(size_t size) {
Francis Dupont's avatar
Francis Dupont committed
116 117 118 119 120 121 122
#ifdef OPENSSL_LEAKS
	void *ptr;

	INSIST(dst__memory_pool != NULL);
	ptr = isc_mem_allocate(dst__memory_pool, size);
	return (ptr);
#else
Mark Andrews's avatar
Mark Andrews committed
123 124
	INSIST(dst__memory_pool != NULL);
	return (isc_mem_allocate(dst__memory_pool, size));
Francis Dupont's avatar
Francis Dupont committed
125
#endif
126 127 128 129
}

static void
mem_free(void *ptr) {
Mark Andrews's avatar
Mark Andrews committed
130
	INSIST(dst__memory_pool != NULL);
131
	if (ptr != NULL)
Mark Andrews's avatar
Mark Andrews committed
132
		isc_mem_free(dst__memory_pool, ptr);
133 134 135 136
}

static void *
mem_realloc(void *ptr, size_t size) {
Francis Dupont's avatar
Francis Dupont committed
137 138 139 140 141 142 143
#ifdef OPENSSL_LEAKS
	void *rptr;

	INSIST(dst__memory_pool != NULL);
	rptr = isc_mem_reallocate(dst__memory_pool, ptr, size);
	return (rptr);
#else
Mark Andrews's avatar
Mark Andrews committed
144
	INSIST(dst__memory_pool != NULL);
145
	return (isc_mem_reallocate(dst__memory_pool, ptr, size));
Francis Dupont's avatar
Francis Dupont committed
146
#endif
147 148
}

Brian Wellington's avatar
Brian Wellington committed
149
isc_result_t
Francis Dupont's avatar
Francis Dupont committed
150
dst__openssl_init(const char *engine) {
151
	isc_result_t result;
Francis Dupont's avatar
Francis Dupont committed
152 153
#ifdef USE_ENGINE
	ENGINE *re;
Francis Dupont's avatar
Francis Dupont committed
154 155 156
#else

	UNUSED(engine);
Francis Dupont's avatar
Francis Dupont committed
157
#endif
158

159 160 161 162 163
#ifdef  DNS_CRYPTO_LEAKS
	CRYPTO_malloc_debug_init();
	CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
#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 168 169
	if (locks == NULL)
		return (ISC_R_NOMEMORY);
	result = isc_mutexblock_init(locks, nlocks);
170 171
	if (result != ISC_R_SUCCESS)
		goto cleanup_mutexalloc;
172 173
	CRYPTO_set_locking_callback(lock_callback);
	CRYPTO_set_id_callback(id_callback);
174

175
	rm = mem_alloc(sizeof(RAND_METHOD));
176 177 178 179
	if (rm == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup_mutexinit;
	}
180 181 182 183 184
	rm->seed = NULL;
	rm->bytes = entropy_get;
	rm->cleanup = NULL;
	rm->add = entropy_add;
	rm->pseudorand = entropy_getpseudo;
185
	rm->status = entropy_status;
Francis Dupont's avatar
Francis Dupont committed
186

187
#ifdef USE_ENGINE
Francis Dupont's avatar
Francis Dupont committed
188
	OPENSSL_config(NULL);
Francis Dupont's avatar
Francis Dupont committed
189 190 191 192 193 194

	if (engine != NULL && *engine == '\0')
		engine = NULL;

	if (engine != NULL) {
		e = ENGINE_by_id(engine);
Francis Dupont's avatar
Francis Dupont committed
195
		if (e == NULL) {
Francis Dupont's avatar
Francis Dupont committed
196
			result = DST_R_NOENGINE;
Francis Dupont's avatar
Francis Dupont committed
197 198
			goto cleanup_rm;
		}
Francis Dupont's avatar
Francis Dupont committed
199 200 201
		/* This will init the engine. */
		if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
			result = DST_R_NOENGINE;
Francis Dupont's avatar
Francis Dupont committed
202 203 204
			goto cleanup_rm;
		}
	}
Francis Dupont's avatar
Francis Dupont committed
205

Francis Dupont's avatar
Francis Dupont committed
206 207 208 209 210 211 212 213 214 215 216 217
	re = ENGINE_get_default_RAND();
	if (re == NULL) {
		re = ENGINE_new();
		if (re == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup_rm;
		}
		ENGINE_set_RAND(re, rm);
		ENGINE_set_default_RAND(re);
		ENGINE_free(re);
	} else
		ENGINE_finish(re);
218
#else
219
	RAND_set_rand_method(rm);
220
#endif /* USE_ENGINE */
Brian Wellington's avatar
Brian Wellington committed
221
	return (ISC_R_SUCCESS);
222

223
#ifdef USE_ENGINE
224
 cleanup_rm:
Francis Dupont's avatar
Francis Dupont committed
225 226 227
	if (e != NULL)
		ENGINE_free(e);
	e = NULL;
228
	mem_free(rm);
Francis Dupont's avatar
Francis Dupont committed
229
	rm = NULL;
230 231
#endif
 cleanup_mutexinit:
232
	CRYPTO_set_locking_callback(NULL);
233
	DESTROYMUTEXBLOCK(locks, nlocks);
234
 cleanup_mutexalloc:
235
	mem_free(locks);
Francis Dupont's avatar
Francis Dupont committed
236
	locks = NULL;
237
	return (result);
Brian Wellington's avatar
Brian Wellington committed
238 239
}

240
void
Mark Andrews's avatar
Mark Andrews committed
241
dst__openssl_destroy() {
242 243 244 245

	/*
	 * Sequence taken from apps_shutdown() in <apps/apps.h>.
	 */
Francis Dupont's avatar
Francis Dupont committed
246 247 248 249 250 251 252
	if (rm != NULL) {
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
		RAND_cleanup();
#endif
		mem_free(rm);
		rm = NULL;
	}
253
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
Francis Dupont's avatar
Francis Dupont committed
254
	CONF_modules_free();
255
#endif
Francis Dupont's avatar
Francis Dupont committed
256
	OBJ_cleanup();
257
	EVP_cleanup();
Francis Dupont's avatar
Francis Dupont committed
258
#if defined(USE_ENGINE)
Francis Dupont's avatar
Francis Dupont committed
259 260 261
	if (e != NULL)
		ENGINE_free(e);
	e = NULL;
262
#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
263 264
	ENGINE_cleanup();
#endif
Francis Dupont's avatar
Francis Dupont committed
265
#endif
266
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
267
	CRYPTO_cleanup_all_ex_data();
268
#endif
269 270
	ERR_clear_error();
	ERR_remove_state(0);
Francis Dupont's avatar
Francis Dupont committed
271
	ERR_free_strings();
272 273 274 275 276

#ifdef  DNS_CRYPTO_LEAKS
	CRYPTO_mem_leaks_fp(stderr);
#endif

277 278 279 280
	if (locks != NULL) {
		CRYPTO_set_locking_callback(NULL);
		DESTROYMUTEXBLOCK(locks, nlocks);
		mem_free(locks);
Francis Dupont's avatar
Francis Dupont committed
281
		locks = NULL;
282
	}
283 284
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
isc_result_t
dst__openssl_toresult(isc_result_t fallback) {
	isc_result_t result = fallback;
	int err = ERR_get_error();

	switch (ERR_GET_REASON(err)) {
	case ERR_R_MALLOC_FAILURE:
		result = ISC_R_NOMEMORY;
		break;
	default:
		break;
	}
	ERR_clear_error();
	return (result);
}

301
#if defined(USE_ENGINE)
Francis Dupont's avatar
Francis Dupont committed
302
ENGINE *
Francis Dupont's avatar
Francis Dupont committed
303
dst__openssl_getengine(const char *engine) {
Francis Dupont's avatar
Francis Dupont committed
304

Francis Dupont's avatar
Francis Dupont committed
305 306
	if (engine == NULL)
		return (NULL);
Francis Dupont's avatar
Francis Dupont committed
307
	if (e == NULL)
Francis Dupont's avatar
Francis Dupont committed
308 309 310 311
		return (NULL);
	if (strcmp(engine, ENGINE_get_id(e)) == 0)
		return (e);
	return (NULL);
Francis Dupont's avatar
Francis Dupont committed
312
}
313
#endif
Francis Dupont's avatar
Francis Dupont committed
314

315 316 317 318
#else /* OPENSSL */

#include <isc/util.h>

Mark Andrews's avatar
Mark Andrews committed
319
EMPTY_TRANSLATION_UNIT
320

321
#endif /* OPENSSL */
322
/*! \file */