2 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
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.
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.
33 * Principal Author: Brian Wellington
34 * $Id: openssl_link.c,v 1.22.112.3 2009/02/11 03:07:01 jinmei Exp $
40 #include <isc/entropy.h>
42 #include <isc/mutex.h>
43 #include <isc/mutexblock.h>
44 #include <isc/string.h>
45 #include <isc/thread.h>
48 #include "dst_internal.h"
49 #include "dst_openssl.h"
51 #include <openssl/err.h>
52 #include <openssl/rand.h>
53 #include <openssl/evp.h>
54 #include <openssl/conf.h>
55 #include <openssl/crypto.h>
57 #if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
62 #include <openssl/engine.h>
65 const char *engine_id = ENGINE_ID;
67 const char *engine_id;
71 static RAND_METHOD *rm = NULL;
73 static isc_mutex_t *locks = NULL;
83 dst__openssl_load_engine(const char *name, const char *engine_id,
84 const char **pre_cmds, int pre_num,
85 const char **post_cmds, int post_num);
89 entropy_get(unsigned char *buf, int num) {
93 result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
94 return (result == ISC_R_SUCCESS ? num : -1);
98 entropy_status(void) {
99 return (dst__entropy_status() > 32);
103 entropy_getpseudo(unsigned char *buf, int num) {
107 result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
108 return (result == ISC_R_SUCCESS ? num : -1);
112 entropy_add(const void *buf, int num, double entropy) {
114 * Do nothing. The only call to this provides no useful data anyway.
122 lock_callback(int mode, int type, const char *file, int line) {
125 if ((mode & CRYPTO_LOCK) != 0)
128 UNLOCK(&locks[type]);
133 return ((unsigned long)isc_thread_self());
137 mem_alloc(size_t size) {
138 INSIST(dst__memory_pool != NULL);
139 return (isc_mem_allocate(dst__memory_pool, size));
143 mem_free(void *ptr) {
144 INSIST(dst__memory_pool != NULL);
146 isc_mem_free(dst__memory_pool, ptr);
150 mem_realloc(void *ptr, size_t size) {
151 INSIST(dst__memory_pool != NULL);
152 return (isc_mem_reallocate(dst__memory_pool, ptr, size));
156 dst__openssl_init() {
159 /* const char *name; */
163 #ifdef DNS_CRYPTO_LEAKS
164 CRYPTO_malloc_debug_init();
165 CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
166 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
168 CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
169 nlocks = CRYPTO_num_locks();
170 locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
172 return (ISC_R_NOMEMORY);
173 result = isc_mutexblock_init(locks, nlocks);
174 if (result != ISC_R_SUCCESS)
175 goto cleanup_mutexalloc;
176 CRYPTO_set_locking_callback(lock_callback);
177 CRYPTO_set_id_callback(id_callback);
179 rm = mem_alloc(sizeof(RAND_METHOD));
181 result = ISC_R_NOMEMORY;
182 goto cleanup_mutexinit;
185 rm->bytes = entropy_get;
187 rm->add = entropy_add;
188 rm->pseudorand = entropy_getpseudo;
189 rm->status = entropy_status;
191 OPENSSL_config(NULL);
193 #ifndef PKCS11_SO_PATH
194 #define PKCS11_SO_PATH "/usr/local/lib/engines/engine_pkcs11.so"
196 #ifndef PKCS11_MODULE_PATH
197 #define PKCS11_MODULE_PATH "/usr/lib/libpkcs11.so"
201 * to use this to config the PIN, add in openssl.cnf:
202 * - at the beginning: "openssl_conf = openssl_def"
203 * - at any place these sections:
205 * engines = engine_section
207 * pkcs11 = pkcs11_section
212 const char *pre_cmds[] = {
213 "SO_PATH", PKCS11_SO_PATH,
215 "MODULE_PATH", PKCS11_MODULE_PATH
217 const char *post_cmds[] = {
218 /* "PIN", "my___pin" */
220 result = dst__openssl_load_engine("pkcs11", "pkcs11",
223 if (result != ISC_R_SUCCESS)
226 #endif /* USE_PKCS11 */
227 if (engine_id != NULL) {
228 e = ENGINE_by_id(engine_id);
230 result = ISC_R_NOTFOUND;
233 if (!ENGINE_init(e)) {
234 result = ISC_R_FAILURE;
238 ENGINE_set_default(e, ENGINE_METHOD_ALL);
241 ENGINE_register_all_complete();
242 for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
245 * Something weird here. If we call ENGINE_finish()
246 * ENGINE_get_default_RAND() will fail.
248 if (ENGINE_init(e)) {
254 re = ENGINE_get_default_RAND();
258 result = ISC_R_NOMEMORY;
261 ENGINE_set_RAND(re, rm);
262 ENGINE_set_default_RAND(re);
268 RAND_set_rand_method(rm);
269 #endif /* USE_ENGINE */
270 return (ISC_R_SUCCESS);
277 CRYPTO_set_locking_callback(NULL);
278 DESTROYMUTEXBLOCK(locks, nlocks);
285 dst__openssl_destroy() {
288 * Sequence taken from apps_shutdown() in <apps/apps.h>.
290 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
291 CONF_modules_unload(1);
294 #if defined(USE_ENGINE)
299 #if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
303 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
304 CRYPTO_cleanup_all_ex_data();
310 #ifdef DNS_CRYPTO_LEAKS
311 CRYPTO_mem_leaks_fp(stderr);
315 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
321 CRYPTO_set_locking_callback(NULL);
322 DESTROYMUTEXBLOCK(locks, nlocks);
328 dst__openssl_toresult(isc_result_t fallback) {
329 isc_result_t result = fallback;
330 int err = ERR_get_error();
332 switch (ERR_GET_REASON(err)) {
333 case ERR_R_MALLOC_FAILURE:
334 result = ISC_R_NOMEMORY;
344 dst__openssl_getengine(const char *name) {
349 #if defined(USE_ENGINE)
357 dst__openssl_setdefault(const char *name) {
361 #if defined(USE_ENGINE)
362 ENGINE_set_default(e, ENGINE_METHOD_ALL);
365 * XXXMPA If the engine does not have a default RAND method
366 * restore our method.
368 return (ISC_R_SUCCESS);
373 * 'name' is the name the engine is known by to the dst library.
374 * This may or may not match the name the engine is known by to
375 * openssl. It is the name that is stored in the private key file.
377 * 'engine_id' is the openssl engine name.
379 * pre_cmds and post_cmds a sequence if command argument pairs
380 * pre_num and post_num are a count of those pairs.
382 * "SO_PATH", PKCS11_SO_PATH ("/usr/local/lib/engines/engine_pkcs11.so")
384 * "MODULE_PATH", PKCS11_MODULE_PATH ("/usr/lib/libpkcs11.so")
387 dst__openssl_load_engine(const char *name, const char *engine_id,
388 const char **pre_cmds, int pre_num,
389 const char **post_cmds, int post_num)
395 if (!strcasecmp(engine_id, "dynamic"))
396 ENGINE_load_dynamic();
397 e = ENGINE_by_id(engine_id);
399 return (ISC_R_NOTFOUND);
401 if (!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) {
403 return (ISC_R_FAILURE);
407 if (!ENGINE_init(e)) {
409 return (ISC_R_FAILURE);
412 * ENGINE_init() returned a functional reference, so free the
413 * structural reference from ENGINE_by_id().
417 if (!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) {
419 return (ISC_R_FAILURE);
426 return (ISC_R_SUCCESS);
428 #endif /* USE_PKCS11 */
432 #include <isc/util.h>
434 EMPTY_TRANSLATION_UNIT