1 /*
2  *
3  * Functions to enable multi-threaded use of crypto libraries.
4  *
5  * OpenSSL -- http://www.openssl.org/docs/crypto/threads.html
6  * Libgcrypt -- http://gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
7  *
8  * This code is based on Curl 7.21.1
9  *
10  * See <medusa-thread-ssl.h> for interface declarations.
11  *
12  */
13 
14 #include "medusa.h"
15 
16 /* In OpenSSL <= 1.0.2, an application had to set locking callbacks to use
17    OpenSSL in a multi-threaded environment. OpenSSL 1.1.0 now finds pthreads
18    or Windows threads, so nothing special is necessary.
19 */
20 #if defined(HAVE_LIBSSL) && (OPENSSL_VERSION_NUMBER < 0x10100005L)
21 static pthread_mutex_t *lockarray;
22 
23 #include <openssl/crypto.h>
lock_callback(int mode,int type,char * file,int line)24 static void lock_callback(int mode, int type, char *file, int line)
25 {
26   (void)file;
27   (void)line;
28   if (mode & CRYPTO_LOCK) {
29     pthread_mutex_lock(&(lockarray[type]));
30   }
31   else {
32     pthread_mutex_unlock(&(lockarray[type]));
33   }
34 }
35 
thread_id(void)36 static unsigned long thread_id(void)
37 {
38   unsigned long ret;
39 
40   ret=(unsigned long)pthread_self();
41   return(ret);
42 }
43 
init_locks_openssl(void)44 void init_locks_openssl(void)
45 {
46   int i;
47 
48   lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
49                                             sizeof(pthread_mutex_t));
50   for (i=0; i<CRYPTO_num_locks(); i++) {
51     pthread_mutex_init(&(lockarray[i]),NULL);
52 
53   }
54 
55   CRYPTO_set_id_callback((unsigned long (*)())thread_id);
56   CRYPTO_set_locking_callback((void (*)())lock_callback);
57 }
58 
kill_locks_openssl(void)59 void kill_locks_openssl(void)
60 {
61   int i;
62 
63   CRYPTO_set_locking_callback(NULL);
64   for (i=0; i<CRYPTO_num_locks(); i++)
65     pthread_mutex_destroy(&(lockarray[i]));
66 
67   OPENSSL_free(lockarray);
68 }
69 #endif
70 
71 #ifdef HAVE_GNUTLS
72 #include <gnutls/gnutls.h>
73 #include <gcrypt.h>
74 
75 GCRY_THREAD_OPTION_PTHREAD_IMPL;
76 
init_locks_gnutls(void)77 void init_locks_gnutls(void)
78 {
79   gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
80   gnutls_global_init();
81 }
82 #endif
83 
init_crypto_locks(void)84 void init_crypto_locks(void)
85 {
86 #if defined(HAVE_LIBSSL) && (OPENSSL_VERSION_NUMBER < 0x10100005L)
87   init_locks_openssl();
88 #endif
89 
90 #ifdef HAVE_GNUTLS
91   init_locks_gnutls();
92 #endif
93 }
94 
kill_crypto_locks(void)95 void kill_crypto_locks(void)
96 {
97 #if defined(HAVE_LIBSSL) && (OPENSSL_VERSION_NUMBER < 0x10100005L)
98   kill_locks_openssl();
99 #endif
100 }
101