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