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