Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / openssl_link.c
blob31171e91e8685fed0ed47e7abcfd52546f720fd3
1 /* $NetBSD: openssl_link.c,v 1.1.1.2 2009/10/25 00:02:31 christos Exp $ */
3 /*
4 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 * Principal Author: Brian Wellington
36 * Id: openssl_link.c,v 1.27 2009/10/05 17:30:49 fdupont Exp
38 #ifdef OPENSSL
40 #include <config.h>
42 #include <isc/entropy.h>
43 #include <isc/mem.h>
44 #include <isc/mutex.h>
45 #include <isc/mutexblock.h>
46 #include <isc/string.h>
47 #include <isc/thread.h>
48 #include <isc/util.h>
50 #include <dst/result.h>
52 #include "dst_internal.h"
53 #include "dst_openssl.h"
55 #include <openssl/err.h>
56 #include <openssl/rand.h>
57 #include <openssl/evp.h>
58 #include <openssl/conf.h>
59 #include <openssl/crypto.h>
61 #if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
62 #define USE_ENGINE 1
63 #endif
65 #ifdef USE_ENGINE
66 #include <openssl/engine.h>
67 #endif
69 static RAND_METHOD *rm = NULL;
71 static isc_mutex_t *locks = NULL;
72 static int nlocks;
74 #ifdef USE_ENGINE
75 static ENGINE *e = NULL;
76 #endif
78 static int
79 entropy_get(unsigned char *buf, int num) {
80 isc_result_t result;
81 if (num < 0)
82 return (-1);
83 result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
84 return (result == ISC_R_SUCCESS ? num : -1);
87 static int
88 entropy_status(void) {
89 return (dst__entropy_status() > 32);
92 static int
93 entropy_getpseudo(unsigned char *buf, int num) {
94 isc_result_t result;
95 if (num < 0)
96 return (-1);
97 result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
98 return (result == ISC_R_SUCCESS ? num : -1);
101 static int
102 entropy_add(const void *buf, int num, double entropy) {
104 * Do nothing. The only call to this provides no useful data anyway.
106 UNUSED(buf);
107 UNUSED(num);
108 UNUSED(entropy);
109 return 0;
112 static void
113 lock_callback(int mode, int type, const char *file, int line) {
114 UNUSED(file);
115 UNUSED(line);
116 if ((mode & CRYPTO_LOCK) != 0)
117 LOCK(&locks[type]);
118 else
119 UNLOCK(&locks[type]);
122 static unsigned long
123 id_callback(void) {
124 return ((unsigned long)isc_thread_self());
127 static void *
128 mem_alloc(size_t size) {
129 #ifdef OPENSSL_LEAKS
130 void *ptr;
132 INSIST(dst__memory_pool != NULL);
133 ptr = isc_mem_allocate(dst__memory_pool, size);
134 return (ptr);
135 #else
136 INSIST(dst__memory_pool != NULL);
137 return (isc_mem_allocate(dst__memory_pool, size));
138 #endif
141 static void
142 mem_free(void *ptr) {
143 INSIST(dst__memory_pool != NULL);
144 if (ptr != NULL)
145 isc_mem_free(dst__memory_pool, ptr);
148 static void *
149 mem_realloc(void *ptr, size_t size) {
150 #ifdef OPENSSL_LEAKS
151 void *rptr;
153 INSIST(dst__memory_pool != NULL);
154 rptr = isc_mem_reallocate(dst__memory_pool, ptr, size);
155 return (rptr);
156 #else
157 INSIST(dst__memory_pool != NULL);
158 return (isc_mem_reallocate(dst__memory_pool, ptr, size));
159 #endif
162 isc_result_t
163 dst__openssl_init(const char *engine) {
164 isc_result_t result;
165 #ifdef USE_ENGINE
166 ENGINE *re;
167 #else
169 UNUSED(engine);
170 #endif
172 #ifdef DNS_CRYPTO_LEAKS
173 CRYPTO_malloc_debug_init();
174 CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
175 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
176 #endif
177 CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
178 nlocks = CRYPTO_num_locks();
179 locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
180 if (locks == NULL)
181 return (ISC_R_NOMEMORY);
182 result = isc_mutexblock_init(locks, nlocks);
183 if (result != ISC_R_SUCCESS)
184 goto cleanup_mutexalloc;
185 CRYPTO_set_locking_callback(lock_callback);
186 CRYPTO_set_id_callback(id_callback);
188 rm = mem_alloc(sizeof(RAND_METHOD));
189 if (rm == NULL) {
190 result = ISC_R_NOMEMORY;
191 goto cleanup_mutexinit;
193 rm->seed = NULL;
194 rm->bytes = entropy_get;
195 rm->cleanup = NULL;
196 rm->add = entropy_add;
197 rm->pseudorand = entropy_getpseudo;
198 rm->status = entropy_status;
200 #ifdef USE_ENGINE
201 OPENSSL_config(NULL);
203 if (engine != NULL && *engine == '\0')
204 engine = NULL;
206 if (engine != NULL) {
207 e = ENGINE_by_id(engine);
208 if (e == NULL) {
209 result = DST_R_NOENGINE;
210 goto cleanup_rm;
212 /* This will init the engine. */
213 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
214 result = DST_R_NOENGINE;
215 goto cleanup_rm;
219 re = ENGINE_get_default_RAND();
220 if (re == NULL) {
221 re = ENGINE_new();
222 if (re == NULL) {
223 result = ISC_R_NOMEMORY;
224 goto cleanup_rm;
226 ENGINE_set_RAND(re, rm);
227 ENGINE_set_default_RAND(re);
228 ENGINE_free(re);
229 } else
230 ENGINE_finish(re);
231 #else
232 RAND_set_rand_method(rm);
233 #endif /* USE_ENGINE */
234 return (ISC_R_SUCCESS);
236 #ifdef USE_ENGINE
237 cleanup_rm:
238 if (e != NULL)
239 ENGINE_free(e);
240 e = NULL;
241 mem_free(rm);
242 rm = NULL;
243 #endif
244 cleanup_mutexinit:
245 CRYPTO_set_locking_callback(NULL);
246 DESTROYMUTEXBLOCK(locks, nlocks);
247 cleanup_mutexalloc:
248 mem_free(locks);
249 locks = NULL;
250 return (result);
253 void
254 dst__openssl_destroy() {
257 * Sequence taken from apps_shutdown() in <apps/apps.h>.
259 if (rm != NULL) {
260 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
261 RAND_cleanup();
262 #endif
263 mem_free(rm);
264 rm = NULL;
266 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
267 CONF_modules_free();
268 #endif
269 OBJ_cleanup();
270 EVP_cleanup();
271 #if defined(USE_ENGINE)
272 if (e != NULL)
273 ENGINE_free(e);
274 e = NULL;
275 #if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
276 ENGINE_cleanup();
277 #endif
278 #endif
279 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
280 CRYPTO_cleanup_all_ex_data();
281 #endif
282 ERR_clear_error();
283 ERR_remove_state(0);
284 ERR_free_strings();
286 #ifdef DNS_CRYPTO_LEAKS
287 CRYPTO_mem_leaks_fp(stderr);
288 #endif
290 if (locks != NULL) {
291 CRYPTO_set_locking_callback(NULL);
292 DESTROYMUTEXBLOCK(locks, nlocks);
293 mem_free(locks);
294 locks = NULL;
298 isc_result_t
299 dst__openssl_toresult(isc_result_t fallback) {
300 isc_result_t result = fallback;
301 int err = ERR_get_error();
303 switch (ERR_GET_REASON(err)) {
304 case ERR_R_MALLOC_FAILURE:
305 result = ISC_R_NOMEMORY;
306 break;
307 default:
308 break;
310 ERR_clear_error();
311 return (result);
314 ENGINE *
315 dst__openssl_getengine(const char *engine) {
317 if (engine == NULL)
318 return (NULL);
319 #if defined(USE_ENGINE)
320 if (e == NULL)
321 return (NULL);
322 if (strcmp(engine, ENGINE_get_id(e)) == 0)
323 return (e);
324 #endif
325 return (NULL);
328 #else /* OPENSSL */
330 #include <isc/util.h>
332 EMPTY_TRANSLATION_UNIT
334 #endif /* OPENSSL */
335 /*! \file */