blob: dfeb91ea99b341f46c4bb9a31864e58a73be6a11 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
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
24static pthread_mutex_t *lockv;
25
26
27static 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
39static void threadid_handler(CRYPTO_THREADID *id)
40{
41 CRYPTO_THREADID_set_numeric(id, threadid());
42}
43#else
44static unsigned long threadid_handler(void)
45{
46 return threadid();
47}
48#endif
49
50
51static 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
67static 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
81static 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
95static 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
107static void sigpipe_handler(int x)
108{
109 (void)x;
110 (void)signal(SIGPIPE, sigpipe_handler);
111}
112#endif
113
114
115int 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
159void 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}