xref: /titanic_53/usr/src/lib/libipsecutil/common/ipsec_libssl_setup.c (revision 6221cd42af599de9b37c1254898231c20c8d01f8)
1a12f8217Spwernau /*
2a12f8217Spwernau  * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3a12f8217Spwernau  * All rights reserved.
4a12f8217Spwernau  *
5a12f8217Spwernau  * This package is an SSL implementation written
6a12f8217Spwernau  * by Eric Young (eay@cryptsoft.com).
7a12f8217Spwernau  * The implementation was written so as to conform with Netscapes SSL.
8a12f8217Spwernau  *
9a12f8217Spwernau  * This library is free for commercial and non-commercial use as long as
10a12f8217Spwernau  * the following conditions are aheared to.  The following conditions
11a12f8217Spwernau  * apply to all code found in this distribution, be it the RC4, RSA,
12a12f8217Spwernau  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13a12f8217Spwernau  * included with this distribution is covered by the same copyright terms
14a12f8217Spwernau  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15a12f8217Spwernau  *
16a12f8217Spwernau  * Copyright remains Eric Young's, and as such any Copyright notices in
17a12f8217Spwernau  * the code are not to be removed.
18a12f8217Spwernau  * If this package is used in a product, Eric Young should be given attribution
19a12f8217Spwernau  * as the author of the parts of the library used.
20a12f8217Spwernau  * This can be in the form of a textual message at program startup or
21a12f8217Spwernau  * in documentation (online or textual) provided with the package.
22a12f8217Spwernau  *
23a12f8217Spwernau  * Redistribution and use in source and binary forms, with or without
24a12f8217Spwernau  * modification, are permitted provided that the following conditions
25a12f8217Spwernau  * are met:
26a12f8217Spwernau  * 1. Redistributions of source code must retain the copyright
27a12f8217Spwernau  *    notice, this list of conditions and the following disclaimer.
28a12f8217Spwernau  * 2. Redistributions in binary form must reproduce the above copyright
29a12f8217Spwernau  *    notice, this list of conditions and the following disclaimer in the
30a12f8217Spwernau  *    documentation and/or other materials provided with the distribution.
31a12f8217Spwernau  * 3. All advertising materials mentioning features or use of this software
32a12f8217Spwernau  *    must display the following acknowledgement:
33a12f8217Spwernau  *    "This product includes cryptographic software written by
34a12f8217Spwernau  *     Eric Young (eay@cryptsoft.com)"
35a12f8217Spwernau  *    The word 'cryptographic' can be left out if the rouines from the library
36a12f8217Spwernau  *    being used are not cryptographic related :-).
37a12f8217Spwernau  * 4. If you include any Windows specific code (or a derivative thereof) from
38a12f8217Spwernau  *    the apps directory (application code) you must include an acknowledgement:
39a12f8217Spwernau  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40a12f8217Spwernau  *
41a12f8217Spwernau  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42a12f8217Spwernau  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43a12f8217Spwernau  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44a12f8217Spwernau  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45a12f8217Spwernau  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46a12f8217Spwernau  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47a12f8217Spwernau  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48a12f8217Spwernau  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49a12f8217Spwernau  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50a12f8217Spwernau  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51a12f8217Spwernau  * SUCH DAMAGE.
52a12f8217Spwernau  *
53a12f8217Spwernau  * The licence and distribution terms for any publically available version or
54a12f8217Spwernau  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55a12f8217Spwernau  * copied and put under another distribution licence
56a12f8217Spwernau  * [including the GNU Public Licence.]
57a12f8217Spwernau  */
58a12f8217Spwernau 
59a12f8217Spwernau /*
60*6221cd42SPaul Wernau  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
61a12f8217Spwernau  * Use is subject to license terms.
62a12f8217Spwernau  */
63a12f8217Spwernau 
64a12f8217Spwernau /*
65a12f8217Spwernau  * Thread setup portions of this code derived from
66*6221cd42SPaul Wernau  * OpenSSL 0.9.x file mt/mttest.c examples
67a12f8217Spwernau  */
68a12f8217Spwernau 
69a12f8217Spwernau #include <stdio.h>
70a12f8217Spwernau #include <stdlib.h>
71a12f8217Spwernau #include <string.h>
72a12f8217Spwernau #include <errno.h>
73a12f8217Spwernau #include <libintl.h>
74a12f8217Spwernau #include <synch.h>
75a12f8217Spwernau #include <thread.h>
76a12f8217Spwernau #include <dlfcn.h>
77a12f8217Spwernau #include <openssl/lhash.h>
78a12f8217Spwernau #include <openssl/crypto.h>
79a12f8217Spwernau #include <openssl/ssl.h>
80a12f8217Spwernau #include <openssl/err.h>
81a12f8217Spwernau #include "ipsec_util.h"
82a12f8217Spwernau 
83a12f8217Spwernau /* OpenSSL function pointers */
84a12f8217Spwernau static X509_NAME *(*d2i_X509_NAME_fn)() = NULL;
85a12f8217Spwernau static int (*X509_NAME_print_ex_fp_fn)() = NULL;
86a12f8217Spwernau static char *(*ERR_get_error_fn)() = NULL;
87a12f8217Spwernau static char *(*ERR_error_string_fn)() = NULL;
88a12f8217Spwernau static void (*SSL_load_error_strings_fn)() = NULL;
89a12f8217Spwernau static void (*ERR_free_strings_fn)() = NULL;
90a12f8217Spwernau static void (*CRYPTO_set_locking_callback_fn)() = NULL;
91a12f8217Spwernau static void (*CRYPTO_set_id_callback_fn)() = NULL;
92dfd65381Svk199839 static void (*X509_NAME_free_fn)() = NULL;
93*6221cd42SPaul Wernau static int (*CRYPTO_num_locks_fn)() = NULL;
94*6221cd42SPaul Wernau static void *(*OPENSSL_malloc_fn)() = NULL;
95*6221cd42SPaul Wernau static void (*OPENSSL_free_fn)() = NULL;
96a12f8217Spwernau 
97a12f8217Spwernau static void solaris_locking_callback(int, int, char *, int);
98a12f8217Spwernau static unsigned long solaris_thread_id(void);
99*6221cd42SPaul Wernau static boolean_t thread_setup(void);
100a12f8217Spwernau /* LINTED E_STATIC_UNUSED */
101a12f8217Spwernau static void thread_cleanup(void);
102a12f8217Spwernau 
103a12f8217Spwernau mutex_t init_lock = DEFAULTMUTEX;
104*6221cd42SPaul Wernau static mutex_t *lock_cs;
105*6221cd42SPaul Wernau static long *lock_count;
106*6221cd42SPaul Wernau 
107*6221cd42SPaul Wernau static boolean_t libssl_loaded = B_FALSE;
108*6221cd42SPaul Wernau static boolean_t libcrypto_loaded = B_FALSE;
109a12f8217Spwernau 
110a12f8217Spwernau void
libssl_load()111a12f8217Spwernau libssl_load()
112a12f8217Spwernau {
113a12f8217Spwernau 	void *dldesc;
114a12f8217Spwernau 
115a12f8217Spwernau 	(void) mutex_lock(&init_lock);
116a12f8217Spwernau 	if (libssl_loaded) {
117a12f8217Spwernau 		(void) mutex_unlock(&init_lock);
118a12f8217Spwernau 		return;
119a12f8217Spwernau 	}
120a12f8217Spwernau 
121a12f8217Spwernau 	dldesc = dlopen(LIBSSL, RTLD_LAZY);
122a12f8217Spwernau 	if (dldesc != NULL) {
123a12f8217Spwernau 		d2i_X509_NAME_fn = (X509_NAME*(*)())dlsym(dldesc,
124a12f8217Spwernau 		    "d2i_X509_NAME");
125a12f8217Spwernau 		if (d2i_X509_NAME_fn == NULL)
126a12f8217Spwernau 			goto libssl_err;
127a12f8217Spwernau 
128a12f8217Spwernau 		X509_NAME_print_ex_fp_fn = (int(*)())dlsym(dldesc,
129a12f8217Spwernau 		    "X509_NAME_print_ex_fp");
130a12f8217Spwernau 		if (X509_NAME_print_ex_fp_fn == NULL)
131a12f8217Spwernau 			goto libssl_err;
132a12f8217Spwernau 
133a12f8217Spwernau 		ERR_get_error_fn = (char *(*)())dlsym(dldesc,
134a12f8217Spwernau 		    "ERR_get_error");
135a12f8217Spwernau 		if (ERR_get_error_fn == NULL)
136a12f8217Spwernau 			goto libssl_err;
137a12f8217Spwernau 
138a12f8217Spwernau 		ERR_error_string_fn = (char *(*)())dlsym(dldesc,
139a12f8217Spwernau 		    "ERR_error_string");
140a12f8217Spwernau 		if (ERR_error_string_fn == NULL)
141a12f8217Spwernau 			goto libssl_err;
142a12f8217Spwernau 
143a12f8217Spwernau 		SSL_load_error_strings_fn = (void(*)())dlsym(dldesc,
144a12f8217Spwernau 		    "SSL_load_error_strings");
145a12f8217Spwernau 		if (SSL_load_error_strings_fn == NULL)
146a12f8217Spwernau 			goto libssl_err;
147a12f8217Spwernau 
148a12f8217Spwernau 		ERR_free_strings_fn = (void(*)())dlsym(dldesc,
149a12f8217Spwernau 		    "ERR_free_strings");
150a12f8217Spwernau 		if (ERR_free_strings_fn == NULL)
151a12f8217Spwernau 			goto libssl_err;
152a12f8217Spwernau 
153a12f8217Spwernau 		CRYPTO_set_locking_callback_fn = (void(*)())dlsym(dldesc,
154a12f8217Spwernau 		    "CRYPTO_set_locking_callback");
155a12f8217Spwernau 		if (CRYPTO_set_locking_callback_fn == NULL)
156a12f8217Spwernau 			goto libssl_err;
157a12f8217Spwernau 
158a12f8217Spwernau 		CRYPTO_set_id_callback_fn = (void(*)())dlsym(dldesc,
159a12f8217Spwernau 		    "CRYPTO_set_id_callback");
160a12f8217Spwernau 		if (CRYPTO_set_id_callback_fn == NULL)
161a12f8217Spwernau 			goto libssl_err;
162a12f8217Spwernau 
163dfd65381Svk199839 		X509_NAME_free_fn = (void(*)())dlsym(dldesc,
164dfd65381Svk199839 		    "X509_NAME_free");
165dfd65381Svk199839 		if (X509_NAME_free_fn == NULL)
166e314c1b2Svk199839 			goto libssl_err;
167e314c1b2Svk199839 
168*6221cd42SPaul Wernau 		if (thread_setup() == B_FALSE)
169*6221cd42SPaul Wernau 			goto libssl_err;
170a12f8217Spwernau 
171a12f8217Spwernau 		libssl_loaded = B_TRUE;
172a12f8217Spwernau 	}
173a12f8217Spwernau 	(void) mutex_unlock(&init_lock);
174a12f8217Spwernau 	return;
175a12f8217Spwernau libssl_err:
176a12f8217Spwernau 	(void) dlclose(dldesc);
177a12f8217Spwernau 	(void) mutex_unlock(&init_lock);
178a12f8217Spwernau }
179a12f8217Spwernau 
180*6221cd42SPaul Wernau void
libcrypto_load()181*6221cd42SPaul Wernau libcrypto_load()
182*6221cd42SPaul Wernau {
183*6221cd42SPaul Wernau 	void *dldesc;
184*6221cd42SPaul Wernau 
185*6221cd42SPaul Wernau 	(void) mutex_lock(&init_lock);
186*6221cd42SPaul Wernau 	if (libcrypto_loaded) {
187*6221cd42SPaul Wernau 		(void) mutex_unlock(&init_lock);
188*6221cd42SPaul Wernau 		return;
189*6221cd42SPaul Wernau 	}
190*6221cd42SPaul Wernau 
191*6221cd42SPaul Wernau 	dldesc = dlopen(LIBCRYPTO, RTLD_LAZY);
192*6221cd42SPaul Wernau 	if (dldesc != NULL) {
193*6221cd42SPaul Wernau 		CRYPTO_num_locks_fn = (int(*)())dlsym(dldesc,
194*6221cd42SPaul Wernau 		    "CRYPTO_num_locks");
195*6221cd42SPaul Wernau 		if (CRYPTO_num_locks_fn == NULL)
196*6221cd42SPaul Wernau 			goto libcrypto_err;
197*6221cd42SPaul Wernau 
198*6221cd42SPaul Wernau 		/*
199*6221cd42SPaul Wernau 		 * OPENSSL_free is really a macro, so we
200*6221cd42SPaul Wernau 		 * need to reference the actual symbol,
201*6221cd42SPaul Wernau 		 * which is CRYPTO_free.
202*6221cd42SPaul Wernau 		 */
203*6221cd42SPaul Wernau 		OPENSSL_free_fn = (void(*)())dlsym(dldesc,
204*6221cd42SPaul Wernau 		    "CRYPTO_free");
205*6221cd42SPaul Wernau 		if (OPENSSL_free_fn == NULL)
206*6221cd42SPaul Wernau 			goto libcrypto_err;
207*6221cd42SPaul Wernau 
208*6221cd42SPaul Wernau 		/*
209*6221cd42SPaul Wernau 		 * OPENSSL_malloc is really a macro, so we
210*6221cd42SPaul Wernau 		 * need to reference the actual symbol,
211*6221cd42SPaul Wernau 		 * which is CRYPTO_malloc.
212*6221cd42SPaul Wernau 		 */
213*6221cd42SPaul Wernau 		OPENSSL_malloc_fn = (void *(*)())dlsym(dldesc,
214*6221cd42SPaul Wernau 		    "CRYPTO_malloc");
215*6221cd42SPaul Wernau 		if (OPENSSL_malloc_fn == NULL)
216*6221cd42SPaul Wernau 			goto libcrypto_err;
217*6221cd42SPaul Wernau 
218*6221cd42SPaul Wernau 		libcrypto_loaded = B_TRUE;
219*6221cd42SPaul Wernau 	}
220*6221cd42SPaul Wernau 	(void) mutex_unlock(&init_lock);
221*6221cd42SPaul Wernau 	return;
222*6221cd42SPaul Wernau libcrypto_err:
223*6221cd42SPaul Wernau 	(void) dlclose(dldesc);
224*6221cd42SPaul Wernau 	(void) mutex_unlock(&init_lock);
225*6221cd42SPaul Wernau }
226*6221cd42SPaul Wernau 
227*6221cd42SPaul Wernau static boolean_t
thread_setup(void)228a12f8217Spwernau thread_setup(void)
229a12f8217Spwernau {
230a12f8217Spwernau 	int i;
231a12f8217Spwernau 
232*6221cd42SPaul Wernau 	if ((lock_cs = OPENSSL_malloc_fn(CRYPTO_num_locks_fn() *
233*6221cd42SPaul Wernau 	    sizeof (mutex_t))) == NULL)
234*6221cd42SPaul Wernau 		return (B_FALSE);
235*6221cd42SPaul Wernau 	if ((lock_count = OPENSSL_malloc_fn(CRYPTO_num_locks_fn() *
236*6221cd42SPaul Wernau 	    sizeof (long))) == NULL) {
237*6221cd42SPaul Wernau 		OPENSSL_free_fn(lock_cs);
238*6221cd42SPaul Wernau 		return (B_FALSE);
239*6221cd42SPaul Wernau 	}
240*6221cd42SPaul Wernau 
241*6221cd42SPaul Wernau 	for (i = 0; i < CRYPTO_num_locks_fn(); i++) {
242a12f8217Spwernau 		lock_count[i] = 0;
243a12f8217Spwernau 		(void) mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
244a12f8217Spwernau 	}
245a12f8217Spwernau 
246a12f8217Spwernau 	CRYPTO_set_id_callback_fn((unsigned long (*)())solaris_thread_id);
247a12f8217Spwernau 	CRYPTO_set_locking_callback_fn((void (*)())solaris_locking_callback);
248*6221cd42SPaul Wernau 	return (B_TRUE);
249a12f8217Spwernau }
250a12f8217Spwernau 
251a12f8217Spwernau static void
thread_cleanup(void)252a12f8217Spwernau thread_cleanup(void)
253a12f8217Spwernau {
254a12f8217Spwernau 	int i;
255a12f8217Spwernau 
256a12f8217Spwernau 	(void) mutex_lock(&init_lock);
257a12f8217Spwernau 	CRYPTO_set_locking_callback_fn(NULL);
258a12f8217Spwernau 	CRYPTO_set_id_callback_fn(NULL);
259*6221cd42SPaul Wernau 	for (i = 0; i < CRYPTO_num_locks_fn(); i++)
260a12f8217Spwernau 		(void) mutex_destroy(&(lock_cs[i]));
261*6221cd42SPaul Wernau 	OPENSSL_free_fn(lock_cs);
262*6221cd42SPaul Wernau 	OPENSSL_free_fn(lock_count);
263a12f8217Spwernau 	(void) mutex_unlock(&init_lock);
264a12f8217Spwernau }
265a12f8217Spwernau 
266a12f8217Spwernau /* ARGSUSED */
267a12f8217Spwernau static void
solaris_locking_callback(int mode,int type,char * file,int line)268a12f8217Spwernau solaris_locking_callback(int mode, int type, char *file, int line)
269a12f8217Spwernau {
270a12f8217Spwernau 	if (mode & CRYPTO_LOCK) {
271a12f8217Spwernau 		(void) mutex_lock(&(lock_cs[type]));
272a12f8217Spwernau 		lock_count[type]++;
273a12f8217Spwernau 	} else {
274a12f8217Spwernau 		(void) mutex_unlock(&(lock_cs[type]));
275a12f8217Spwernau 	}
276a12f8217Spwernau }
277a12f8217Spwernau 
278a12f8217Spwernau static unsigned long
solaris_thread_id(void)279a12f8217Spwernau solaris_thread_id(void)
280a12f8217Spwernau {
281a12f8217Spwernau 	unsigned long ret;
282a12f8217Spwernau 
283a12f8217Spwernau 	ret = (unsigned long)thr_self();
284a12f8217Spwernau 	return (ret);
285a12f8217Spwernau }
286a12f8217Spwernau 
287a12f8217Spwernau void
print_asn1_name(FILE * file,const unsigned char * buf,long buflen)288a12f8217Spwernau print_asn1_name(FILE *file, const unsigned char *buf, long buflen)
289a12f8217Spwernau {
290*6221cd42SPaul Wernau 	libcrypto_load();
291*6221cd42SPaul Wernau 	if (libcrypto_loaded)
292a12f8217Spwernau 		libssl_load();
293a12f8217Spwernau 
294*6221cd42SPaul Wernau 	if (libssl_loaded && libcrypto_loaded) {
295dfd65381Svk199839 		X509_NAME *x509name = NULL;
296a12f8217Spwernau 		const unsigned char *p;
297a12f8217Spwernau 
298a12f8217Spwernau 		/* Make an effort to decode the ASN1 encoded name */
299a12f8217Spwernau 		SSL_load_error_strings_fn();
300a12f8217Spwernau 
301dfd65381Svk199839 		/*
302dfd65381Svk199839 		 * Temporary variable is mandatory per d2i_X509(3). Upcoming
303dfd65381Svk199839 		 * call to d2i_X509_NAME_fn() will change the 'p' pointer.
304dfd65381Svk199839 		 */
305a12f8217Spwernau 		p = buf;
306a12f8217Spwernau 
307dfd65381Svk199839 		x509name = d2i_X509_NAME_fn(NULL, &p, buflen);
308dfd65381Svk199839 		if (x509name != NULL) {
309dfd65381Svk199839 			(void) X509_NAME_print_ex_fp_fn(file, x509name, 0,
310a12f8217Spwernau 			    (ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE |
311a12f8217Spwernau 			    XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN));
312dfd65381Svk199839 			X509_NAME_free_fn(x509name);
313a12f8217Spwernau 			(void) fprintf(file, "\n");
314a12f8217Spwernau 		} else {
315a12f8217Spwernau 			char errbuf[80];
316a12f8217Spwernau 
317a12f8217Spwernau 			(void) fprintf(file, "\n# %s\n",
318a12f8217Spwernau 			    ERR_error_string_fn(ERR_get_error_fn(), errbuf));
319a12f8217Spwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
320a12f8217Spwernau 			    "<cannot interpret>\n"));
321a12f8217Spwernau 		}
322a12f8217Spwernau 		ERR_free_strings_fn();
323a12f8217Spwernau 	} else {
324a12f8217Spwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "<cannot print>\n"));
325a12f8217Spwernau 	}
326a12f8217Spwernau }
327