From e14b375487af2b738a4b20c02433d3fa63ecd6e9 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 3 Jun 2014 20:04:46 +0200
Subject: [PATCH] vtls: make the random function mandatory in the TLS backend

To force each to really attempt to provide proper random.
---
 lib/vtls/curl_darwinssl.c |  7 +++----
 lib/vtls/curl_darwinssl.h | 10 ++++------
 lib/vtls/gtls.c           | 13 ++++++++-----
 lib/vtls/gtls.h           | 11 ++++-------
 lib/vtls/nss.c            | 11 +++++++----
 lib/vtls/nssg.h           |  9 ++++-----
 lib/vtls/openssl.c        | 11 +++++++----
 lib/vtls/openssl.h        |  9 ++++-----
 lib/vtls/vtls.c           | 23 +++++++++--------------
 lib/vtls/vtls.h           | 12 +++++-------
 10 files changed, 55 insertions(+), 61 deletions(-)

diff --git a/lib/vtls/curl_darwinssl.c b/lib/vtls/curl_darwinssl.c
index 1ff5c24..480e06e 100644
--- a/lib/vtls/curl_darwinssl.c
+++ b/lib/vtls/curl_darwinssl.c
@@ -2265,13 +2265,12 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn,
   }
   else
     return false;
 }
 
-void Curl_darwinssl_random(struct SessionHandle *data,
-                           unsigned char *entropy,
-                           size_t length)
+int Curl_darwinssl_random(unsigned char *entropy,
+                          size_t length)
 {
   /* arc4random_buf() isn't available on cats older than Lion, so let's
      do this manually for the benefit of the older cats. */
   size_t i;
   u_int32_t random_number = 0;
@@ -2281,11 +2280,11 @@ void Curl_darwinssl_random(struct SessionHandle *data,
       random_number = arc4random();
     entropy[i] = random_number & 0xFF;
     random_number >>= 8;
   }
   i = random_number = 0;
-  (void)data;
+  return 0;
 }
 
 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
                            size_t tmplen,
                            unsigned char *md5sum, /* output */
diff --git a/lib/vtls/curl_darwinssl.h b/lib/vtls/curl_darwinssl.h
index 432d3d7..25ad3d4 100644
--- a/lib/vtls/curl_darwinssl.h
+++ b/lib/vtls/curl_darwinssl.h
@@ -5,11 +5,11 @@
  *  Project                     ___| | | |  _ \| |
  *                             / __| | | | |_) | |
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2013, Nick Zitzmann, <nickzman@gmail.com>.
+ * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@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.
  *
@@ -42,20 +42,18 @@ size_t Curl_darwinssl_version(char *buffer, size_t size);
 int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
 int Curl_darwinssl_check_cxn(struct connectdata *conn);
 bool Curl_darwinssl_data_pending(const struct connectdata *conn,
                                  int connindex);
 
-void Curl_darwinssl_random(struct SessionHandle *data,
-                           unsigned char *entropy,
-                           size_t length);
+int Curl_darwinssl_random(unsigned char *entropy,
+                          size_t length);
 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
                            size_t tmplen,
                            unsigned char *md5sum, /* output */
                            size_t md5len);
 
 /* this backend provides these functions: */
-#define have_curlssl_random 1
 #define have_curlssl_md5sum 1
 
 /* API setup for SecureTransport */
 #define curlssl_init() (1)
 #define curlssl_cleanup() Curl_nop_stmt
@@ -69,10 +67,10 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
 #define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
 #define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
 #define curlssl_version Curl_darwinssl_version
 #define curlssl_check_cxn Curl_darwinssl_check_cxn
 #define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
-#define curlssl_random(x,y,z) Curl_darwinssl_random(x,y,z)
+#define curlssl_random(x,y,z) Curl_darwinssl_random(y,z)
 #define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
 
 #endif /* USE_DARWINSSL */
 #endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index f77ce66..65a849d 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -1172,11 +1172,11 @@ void Curl_gtls_session_free(void *ptr)
 size_t Curl_gtls_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
 }
 
-int Curl_gtls_seed(struct SessionHandle *data)
+static int Curl_gtls_seed(struct SessionHandle *data)
 {
   /* we have the "SSL is seeded" boolean static to prevent multiple
      time-consuming seedings in vain */
   static bool ssl_seeded = FALSE;
 
@@ -1196,21 +1196,24 @@ int Curl_gtls_seed(struct SessionHandle *data)
     ssl_seeded = TRUE;
   }
   return 0;
 }
 
-void Curl_gtls_random(struct SessionHandle *data,
-                      unsigned char *entropy,
-                      size_t length)
+/* data might be NULL! */
+int Curl_gtls_random(struct SessionHandle *data,
+                     unsigned char *entropy,
+                     size_t length)
 {
 #if defined(USE_GNUTLS_NETTLE)
   (void)data;
   gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
 #elif defined(USE_GNUTLS)
-  Curl_gtls_seed(data); /* Initiate the seed if not already done */
+  if(data)
+    Curl_gtls_seed(data); /* Initiate the seed if not already done */
   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
 #endif
+  return 0;
 }
 
 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum, /* output */
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index 453542e..9f99042 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -5,11 +5,11 @@
  *  Project                     ___| | | |  _ \| |
  *                             / __| | | | |_) | |
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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.
  *
@@ -43,22 +43,19 @@ void Curl_gtls_close_all(struct SessionHandle *data);
 void Curl_gtls_close(struct connectdata *conn, int sockindex);
 
 void Curl_gtls_session_free(void *ptr);
 size_t Curl_gtls_version(char *buffer, size_t size);
 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
-int Curl_gtls_seed(struct SessionHandle *data);
-
-void Curl_gtls_random(struct SessionHandle *data,
-                      unsigned char *entropy,
-                      size_t length);
+int Curl_gtls_random(struct SessionHandle *data,
+                     unsigned char *entropy,
+                     size_t length);
 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum, /* output */
                       size_t md5len);
 
 /* this backend provides these functions: */
-#define have_curlssl_random 1
 #define have_curlssl_md5sum 1
 
 /* API setup for GnuTLS */
 #define curlssl_init Curl_gtls_init
 #define curlssl_cleanup Curl_gtls_cleanup
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index c1eec41..537e29b 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1881,20 +1881,23 @@ int Curl_nss_seed(struct SessionHandle *data)
 {
   /* make sure that NSS is initialized */
   return !!Curl_nss_force_init(data);
 }
 
-void Curl_nss_random(struct SessionHandle *data,
-                     unsigned char *entropy,
-                     size_t length)
+/* data might be NULL */
+int Curl_nss_random(struct SessionHandle *data,
+                    unsigned char *entropy,
+                    size_t length)
 {
-  Curl_nss_seed(data);  /* Initiate the seed if not already done */
+  if(data)
+    Curl_nss_seed(data);  /* Initiate the seed if not already done */
   if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
     /* no way to signal a failure from here, we have to abort */
     failf(data, "PK11_GenerateRandom() failed, calling abort()...");
     abort();
   }
+  return 0;
 }
 
 void Curl_nss_md5sum(unsigned char *tmp, /* input */
                      size_t tmplen,
                      unsigned char *md5sum, /* output */
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index 21e96ce..d441de9 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -5,11 +5,11 @@
  *  Project                     ___| | | |  _ \| |
  *                             / __| | | | |_) | |
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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.
  *
@@ -49,21 +49,20 @@ int Curl_nss_check_cxn(struct connectdata *cxn);
 int Curl_nss_seed(struct SessionHandle *data);
 
 /* initialize NSS library if not already */
 CURLcode Curl_nss_force_init(struct SessionHandle *data);
 
-void Curl_nss_random(struct SessionHandle *data,
-                     unsigned char *entropy,
-                     size_t length);
+int Curl_nss_random(struct SessionHandle *data,
+                    unsigned char *entropy,
+                    size_t length);
 
 void Curl_nss_md5sum(unsigned char *tmp, /* input */
                      size_t tmplen,
                      unsigned char *md5sum, /* output */
                      size_t md5len);
 
 /* this backend provides these functions: */
-#define have_curlssl_random 1
 #define have_curlssl_md5sum 1
 
 /* API setup for NSS */
 #define curlssl_init Curl_nss_init
 #define curlssl_cleanup Curl_nss_cleanup
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 0e9c8f0..fd41ed4 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -256,11 +256,11 @@ static int ossl_seed(struct SessionHandle *data)
 
   infof(data, "libcurl is now using a weak random seed!\n");
   return nread;
 }
 
-int Curl_ossl_seed(struct SessionHandle *data)
+static int Curl_ossl_seed(struct SessionHandle *data)
 {
   /* we have the "SSL is seeded" boolean static to prevent multiple
      time-consuming seedings in vain */
   static bool ssl_seeded = FALSE;
 
@@ -2861,15 +2861,18 @@ size_t Curl_ossl_version(char *buffer, size_t size)
 #endif /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */
 
 #endif /* YASSL_VERSION */
 }
 
-void Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
-                      size_t length)
+/* can be called with data == NULL */
+int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+                     size_t length)
 {
-  Curl_ossl_seed(data); /* Initiate the seed if not already done */
+  if(data)
+    Curl_ossl_seed(data); /* Initiate the seed if not already done */
   RAND_bytes(entropy, curlx_uztosi(length));
+  return 0; /* 0 as in no problem */
 }
 
 void Curl_ossl_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum /* output */,
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index 07448b5..fecad7f 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -59,24 +59,23 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
 int Curl_ossl_init(void);
 void Curl_ossl_cleanup(void);
 
 size_t Curl_ossl_version(char *buffer, size_t size);
 int Curl_ossl_check_cxn(struct connectdata *cxn);
-int Curl_ossl_seed(struct SessionHandle *data);
-
 int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
 bool Curl_ossl_data_pending(const struct connectdata *conn,
                             int connindex);
-void Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
-                      size_t length);
+
+/* return 0 if a find random is filled in */
+int Curl_ossl_random(struct SessionHandle *data, unsigned char *entropy,
+                     size_t length);
 void Curl_ossl_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum /* output */,
                       size_t unused);
 
 /* this backend provides these functions: */
-#define have_curlssl_random 1
 #define have_curlssl_md5sum 1
 
 /* API setup for OpenSSL */
 #define curlssl_init Curl_ossl_init
 #define curlssl_cleanup Curl_ossl_cleanup
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index ab7274a..3a44a5f 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -3,11 +3,11 @@
  *  Project                     ___| | | |  _ \| |
  *                             / __| | | | |_) | |
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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.
  *
@@ -195,18 +195,16 @@ unsigned int Curl_rand(struct SessionHandle *data)
 {
   unsigned int r;
   static unsigned int randseed;
   static bool seeded = FALSE;
 
-#ifndef have_curlssl_random
-  (void)data;
-#else
-  if(data) {
-    Curl_ssl_random(data, (unsigned char *)&r, sizeof(r));
+  /* data may be NULL! */
+  if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
     return r;
-  }
-#endif
+
+  /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
+     instead perform a "best effort" */
 
 #ifdef RANDOM_FILE
   if(!seeded) {
     /* if there's a random file to read a seed from, use it */
     int fd = open(RANDOM_FILE, O_RDONLY);
@@ -220,10 +218,11 @@ unsigned int Curl_rand(struct SessionHandle *data)
   }
 #endif
 
   if(!seeded) {
     struct timeval now = curlx_tvnow();
+    infof(data, "WARNING: Using weak random seed\n");
     randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
     randseed = randseed * 1103515245 + 12345;
     randseed = randseed * 1103515245 + 12345;
     randseed = randseed * 1103515245 + 12345;
     seeded = TRUE;
@@ -663,20 +662,16 @@ CURLcode Curl_ssl_push_certinfo(struct SessionHandle *data,
   size_t valuelen = strlen(value);
 
   return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
 }
 
-/* these functions are only provided by some SSL backends */
-
-#ifdef have_curlssl_random
-void Curl_ssl_random(struct SessionHandle *data,
+int Curl_ssl_random(struct SessionHandle *data,
                      unsigned char *entropy,
                      size_t length)
 {
-  curlssl_random(data, entropy, length);
+  return curlssl_random(data, entropy, length);
 }
-#endif
 
 #ifdef have_curlssl_md5sum
 void Curl_ssl_md5sum(unsigned char *tmp, /* input */
                      size_t tmplen,
                      unsigned char *md5sum, /* output */
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 8f977a3..5f58cbd 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -5,11 +5,11 @@
  *  Project                     ___| | | |  _ \| |
  *                             / __| | | | |_) | |
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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.
  *
@@ -86,23 +86,21 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
 /* Kill a single session ID entry in the cache */
 void Curl_ssl_kill_session(struct curl_ssl_session *session);
 /* delete a session from the cache */
 void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
 
-/* get N random bytes into the buffer */
-void Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer,
-                     size_t length);
+/* get N random bytes into the buffer, return 0 if a find random is filled
+   in */
+int Curl_ssl_random(struct SessionHandle *data, unsigned char *buffer,
+                    size_t length);
 void Curl_ssl_md5sum(unsigned char *tmp, /* input */
                      size_t tmplen,
                      unsigned char *md5sum, /* output */
                      size_t md5len);
 
 #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
 
-#ifdef have_curlssl_random
-#define HAVE_CURL_SSL_RANDOM
-#endif
 #ifdef have_curlssl_md5sum
 #define HAVE_CURL_SSL_MD5SUM
 #endif
 
 #else
-- 
2.0.0

