1 /**
2 * @file openssl.c OpenSSL initialisation and multi-threading routines
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #ifdef HAVE_SIGNAL
7 #include <signal.h>
8 #endif
9 #ifdef HAVE_PTHREAD
10 #include <pthread.h>
11 #endif
12 #include <openssl/crypto.h>
13 #include <openssl/ssl.h>
14 #include <openssl/err.h>
15 #include <re_types.h>
16 #include <re_lock.h>
17 #include <re_mem.h>
18 #include "main.h"
19
20
21 #if defined (HAVE_PTHREAD) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
22
23
24 static pthread_mutex_t *lockv;
25
26
threadid(void)27 static inline unsigned long threadid(void)
28 {
29 #if defined (DARWIN) || defined (FREEBSD) || defined (OPENBSD) || \
30 defined (NETBSD) || defined (DRAGONFLY)
31 return (unsigned long)(void *)pthread_self();
32 #else
33 return (unsigned long)pthread_self();
34 #endif
35 }
36
37
38 #if OPENSSL_VERSION_NUMBER >= 0x10000000
threadid_handler(CRYPTO_THREADID * id)39 static void threadid_handler(CRYPTO_THREADID *id)
40 {
41 CRYPTO_THREADID_set_numeric(id, threadid());
42 }
43 #else
threadid_handler(void)44 static unsigned long threadid_handler(void)
45 {
46 return threadid();
47 }
48 #endif
49
50
locking_handler(int mode,int type,const char * file,int line)51 static void locking_handler(int mode, int type, const char *file, int line)
52 {
53 (void)file;
54 (void)line;
55
56 if (mode & CRYPTO_LOCK)
57 (void)pthread_mutex_lock(&lockv[type]);
58 else
59 (void)pthread_mutex_unlock(&lockv[type]);
60 }
61
62
63 #endif
64
65
66 #if OPENSSL_VERSION_NUMBER < 0x10100000L
dynlock_create_handler(const char * file,int line)67 static struct CRYPTO_dynlock_value *dynlock_create_handler(const char *file,
68 int line)
69 {
70 struct lock *lock;
71 (void)file;
72 (void)line;
73
74 if (lock_alloc(&lock))
75 return NULL;
76
77 return (struct CRYPTO_dynlock_value *)lock;
78 }
79
80
dynlock_lock_handler(int mode,struct CRYPTO_dynlock_value * l,const char * file,int line)81 static void dynlock_lock_handler(int mode, struct CRYPTO_dynlock_value *l,
82 const char *file, int line)
83 {
84 struct lock *lock = (struct lock *)l;
85 (void)file;
86 (void)line;
87
88 if (mode & CRYPTO_LOCK)
89 lock_write_get(lock);
90 else
91 lock_rel(lock);
92 }
93
94
dynlock_destroy_handler(struct CRYPTO_dynlock_value * l,const char * file,int line)95 static void dynlock_destroy_handler(struct CRYPTO_dynlock_value *l,
96 const char *file, int line)
97 {
98 (void)file;
99 (void)line;
100
101 mem_deref(l);
102 }
103 #endif
104
105
106 #ifdef SIGPIPE
sigpipe_handler(int x)107 static void sigpipe_handler(int x)
108 {
109 (void)x;
110 (void)signal(SIGPIPE, sigpipe_handler);
111 }
112 #endif
113
114
openssl_init(void)115 int openssl_init(void)
116 {
117 #if defined (HAVE_PTHREAD) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
118 int err, i;
119
120 lockv = mem_zalloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks(), NULL);
121 if (!lockv)
122 return ENOMEM;
123
124 for (i=0; i<CRYPTO_num_locks(); i++) {
125
126 err = pthread_mutex_init(&lockv[i], NULL);
127 if (err) {
128 lockv = mem_deref(lockv);
129 return err;
130 }
131 }
132
133 #if OPENSSL_VERSION_NUMBER >= 0x10000000
134 CRYPTO_THREADID_set_callback(threadid_handler);
135 #else
136 CRYPTO_set_id_callback(threadid_handler);
137 #endif
138
139 CRYPTO_set_locking_callback(locking_handler);
140 #endif
141
142 #if OPENSSL_VERSION_NUMBER < 0x10100000L
143 CRYPTO_set_dynlock_create_callback(dynlock_create_handler);
144 CRYPTO_set_dynlock_lock_callback(dynlock_lock_handler);
145 CRYPTO_set_dynlock_destroy_callback(dynlock_destroy_handler);
146 #endif
147
148 #ifdef SIGPIPE
149 (void)signal(SIGPIPE, sigpipe_handler);
150 #endif
151
152 SSL_library_init();
153 SSL_load_error_strings();
154
155 return 0;
156 }
157
158
openssl_close(void)159 void openssl_close(void)
160 {
161 ERR_free_strings();
162 #if defined (HAVE_PTHREAD) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
163 lockv = mem_deref(lockv);
164 #endif
165 }
166