PolarSSL: pthread support for entropy
authorWillem Sparreboom <w.sparreboom@offspark.com>
Mon, 28 Jan 2013 17:31:22 +0000 (18:31 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 15 Feb 2013 22:30:20 +0000 (23:30 +0100)
Added pthread support for polarssl entropy if --enable-threaded-resolver
config flag is set and pthread.h can be found.

lib/Makefile.inc
lib/polarssl.c
lib/polarssl.h
lib/polarsslthreadlock.c [new file with mode: 0755]
lib/polarsslthreadlock.h [new file with mode: 0755]

index 5b73865..96b3228 100644 (file)
@@ -20,12 +20,12 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
   qssl.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c          \
   curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c   \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c                \
-  curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c           \
-  idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c  \
-  asyn-ares.c asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c   \
-  curl_ntlm_core.c curl_ntlm_msgs.c curl_sasl.c curl_schannel.c                \
-  curl_multibyte.c curl_darwinssl.c hostcheck.c                         \
-  bundles.c conncache.c
+  polarsslthreadlock.c curl_rtmp.c openldap.c curl_gethostname.c       \
+  gopher.c axtls.c idn_win32.c http_negotiate_sspi.c cyassl.c          \
+  http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c     \
+  curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c         \
+  curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c                \
+  hostcheck.c bundles.c conncache.c
 
 HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h      \
   progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h     \
@@ -36,12 +36,12 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h   \
   curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h      \
   strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h curl_setup.h        \
   transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h   \
-  tftp.h sockaddr.h splay.h strdup.h socks.h ssh.h nssg.h              \
-  curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h        \
+  tftp.h sockaddr.h splay.h strdup.h socks.h ssh.h nssg.h curl_base64.h        \
+  rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h              \
   curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \
-  warnless.h curl_hmac.h polarssl.h curl_rtmp.h curl_gethostname.h     \
-  gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h        \
-  curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h curl_ntlm_msgs.h       \
-  curl_sasl.h curl_schannel.h curl_multibyte.h curl_darwinssl.h                \
-  hostcheck.h bundles.h conncache.h curl_setup_once.h multihandle.h     \
-  setup-vms.h
+  warnless.h curl_hmac.h polarssl.h polarsslthreadlock.h curl_rtmp.h   \
+  curl_gethostname.h gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h        \
+  asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h     \
+  curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h                \
+  curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h \
+  multihandle.h setup-vms.h
index 09bd95a..db1380e 100644 (file)
 #include "select.h"
 #include "rawstr.h"
 
+/* apply threading? */
+#if defined(USE_THREADS_POSIX)
+#define THREADING_SUPPORT
+#include "polarsslthreadlock.h"
+#endif /* USE_THREADS_POSIX */
+
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
 #include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
 
+#if defined(THREADING_SUPPORT) && POLARSSL_VERSION_NUMBER>0x01010000
+static entropy_context entropy;
+
+static int  entropy_init_initialized  = 0;
+
+/* start of entropy_init_mutex() */
+static void entropy_init_mutex(entropy_context *ctx)
+{
+    /* lock 0 = entropy_init_mutex() */
+    polarsslthreadlock_lock_function(0);
+    if(entropy_init_initialized == 0)
+    {
+        entropy_init(ctx);
+        entropy_init_initialized = 1;
+    }
+    polarsslthreadlock_unlock_function(0);
+}
+/* end of entropy_init_mutex() */
+
+/* start of entropy_func_mutex() */
+static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
+{
+    int ret;
+       /* lock 1 = entropy_func_mutex() */
+    polarsslthreadlock_lock_function(1);
+    ret = entropy_func(data, output, len);
+    polarsslthreadlock_unlock_function(1);
+       
+       return ret;
+}
+/* end of entropy_func_mutex() */
+
+#endif /* THREADING_SUPPORT && POLARSSL_VERSION_NUMBER>0x01010000 */
 
 /* Define this to enable lots of debugging for PolarSSL */
 #undef POLARSSL_DEBUG
@@ -128,6 +167,18 @@ polarssl_connect_step1(struct connectdata *conn,
 #if POLARSSL_VERSION_NUMBER<0x01010000
   havege_init(&connssl->hs);
 #else
+#ifdef THREADING_SUPPORT
+  entropy_init_mutex(&entropy);
+
+  if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
+                           connssl->ssn.id, connssl->ssn.length)) != 0)
+  {
+#ifdef POLARSSL_ERROR_C
+     error_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* POLARSSL_ERROR_C */
+        failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf);
+  }
+#else
   entropy_init(&connssl->entropy);
 
   if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
@@ -138,6 +189,7 @@ polarssl_connect_step1(struct connectdata *conn,
 #endif /* POLARSSL_ERROR_C */
         failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf);
   }
+#endif /* THREADING_SUPPORT */
 #endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
 
   /* Load the trusted CA */
@@ -637,4 +689,24 @@ Curl_polarssl_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
-#endif
+/*
+ * return 0 error initializing SSL
+ * return 1 SSL initialized successfully
+ */
+int polarssl_init(void)
+{
+#ifdef THREADING_SUPPORT
+  return polarsslthreadlock_thread_setup();
+#else /* THREADING_SUPPORT */
+  return 1;
+#endif /* THREADING_SUPPORT */   
+}
+
+void polarssl_cleanup(void)
+{
+#ifdef THREADING_SUPPORT
+  polarsslthreadlock_thread_cleanup();
+#endif /* THREADING_SUPPORT */
+}
+
+#endif /* USE_POLARSSL */
index 12b3db2..af3b28b 100644 (file)
 
 #ifdef USE_POLARSSL
 
+/* Called on first use PolarSSL, setup threading if supported */
+int  polarssl_init(void);
+void polarssl_cleanup(void);
+
+
 CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
 
 CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
@@ -43,8 +48,8 @@ size_t Curl_polarssl_version(char *buffer, size_t size);
 int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
 
 /* API setup for PolarSSL */
-#define curlssl_init() (1)
-#define curlssl_cleanup() Curl_nop_stmt
+#define curlssl_init() polarssl_init()
+#define curlssl_cleanup() polarssl_cleanup()
 #define curlssl_connect Curl_polarssl_connect
 #define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking
 #define curlssl_session_free(x)  Curl_polarssl_session_free(x)
diff --git a/lib/polarsslthreadlock.c b/lib/polarsslthreadlock.c
new file mode 100755 (executable)
index 0000000..fc9c11f
--- /dev/null
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+#if defined(USE_THREADS_POSIX)
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#define MUTEX_TYPE       pthread_mutex_t
+#endif /* HAVE_PTHREAD_H */
+#endif /* USE_THREADS_POSIX */
+
+#include "polarsslthreadlock.h"
+
+/* number of thread locks */
+#define NUMT                    2
+
+/* This array will store all of the mutexes available to PolarSSL. */
+static MUTEX_TYPE *mutex_buf = NULL;
+
+int polarsslthreadlock_thread_setup(void)
+{
+  int i;
+  int ret;
+
+  mutex_buf = malloc(NUMT * sizeof(MUTEX_TYPE));
+  if (!mutex_buf)
+    return 0;     /* error, no number of threads defined */
+
+#ifdef HAVE_PTHREAD_H
+  for (i = 0;  i < NUMT;  i++)
+  {
+    ret = pthread_mutex_init(&mutex_buf[i], NULL);
+       if(ret)
+          return 0; /* pthread_mutex_init failed */
+  }
+#endif /* HAVE_PTHREAD_H */
+
+  return 1; /* OK */
+}
+
+int polarsslthreadlock_thread_cleanup(void)
+{
+  int i;
+  int ret;
+  
+  if (!mutex_buf)
+    return 0; /* error, no threads locks defined */
+
+#ifdef HAVE_PTHREAD_H
+  for (i = 0; i < NUMT; i++)
+  {
+    ret = pthread_mutex_destroy(&mutex_buf[i]);
+       if(ret)
+          return 0; /* pthread_mutex_destroy failed */
+  } 
+#endif /* HAVE_PTHREAD_H */
+  free(mutex_buf);
+  mutex_buf = NULL;
+
+  return 1; /* OK */
+}
+
+int polarsslthreadlock_lock_function(int n)
+{
+  int ret;
+#ifdef HAVE_PTHREAD_H
+  if(n < NUMT)
+  {
+    ret = pthread_mutex_lock(&mutex_buf[n]);
+       if(ret)
+       {
+         DEBUGF(fprintf(stderr, "Error: pthread_mutex_lock failed\n"));
+         return 0; /* pthread_mutex_lock failed */
+       }
+  } 
+#endif /* HAVE_PTHREAD_H */
+  return 1; /* OK */
+}
+
+int polarsslthreadlock_unlock_function(int n)
+{
+  int ret;
+#ifdef HAVE_PTHREAD_H
+  if(n < NUMT)
+  {
+    ret = pthread_mutex_unlock(&mutex_buf[n]);
+       if(ret)
+       {
+         DEBUGF(fprintf(stderr, "Error: pthread_mutex_unlock failed\n"));
+         return 0; /* pthread_mutex_unlock failed */
+       }
+  }
+#endif /* HAVE_PTHREAD_H */
+  return 1; /* OK */
+}
+
+#endif /* USE_POLARSSL */
diff --git a/lib/polarsslthreadlock.h b/lib/polarsslthreadlock.h
new file mode 100755 (executable)
index 0000000..c793222
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_POLARSSLTHREADLOCK_H
+#define HEADER_CURL_POLARSSLTHREADLOCK_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_POLARSSL
+
+int polarsslthreadlock_thread_setup(void);
+int polarsslthreadlock_thread_cleanup(void);
+int polarsslthreadlock_lock_function(int n);
+int polarsslthreadlock_unlock_function(int n);
+
+#endif /* USE_POLARSSL */
+#endif /* HEADER_CURL_POLARSSLTHREADLOCK_H */