Remove remaining calls to the old lock functions.

|SSL_CTX| and |X509_STORE| have grown their own locks. Several static
locks have been added to hack around not being able to use a
|CRYPTO_once_t| in public headers. Lastly, support for calling
|SSL_CTX_set_generate_session_id| concurrently with active connections
has been removed. No other property of an |SSL_CTX| works like that.

Change-Id: Iff5fe3ee3fdd6ea9c9daee96f850b107ad8a6bca
Reviewed-on: https://boringssl-review.googlesource.com/4775
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c
index 5d59c00..08f20aa 100644
--- a/crypto/x509v3/pcy_cache.c
+++ b/crypto/x509v3/pcy_cache.c
@@ -60,6 +60,7 @@
 #include <openssl/x509v3.h>
 
 #include "pcy_int.h"
+#include "../internal.h"
 
 
 static int policy_data_cmp(const X509_POLICY_DATA **a,
@@ -243,18 +244,30 @@
 	OPENSSL_free(cache);
 	}
 
+/* g_x509_policy_cache_lock is used to protect against concurrent calls to
+ * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t|
+ * in the |X509| structure, but |CRYPTO_once_t| isn't public. */
+static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock =
+    CRYPTO_STATIC_MUTEX_INIT;
+
 const X509_POLICY_CACHE *policy_cache_set(X509 *x)
 	{
+	X509_POLICY_CACHE *cache;
 
+	CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
+	cache = x->policy_cache;
+	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+
+	if (cache != NULL)
+		return cache;
+
+	CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
 	if (x->policy_cache == NULL)
-		{
-		CRYPTO_w_lock(CRYPTO_LOCK_X509);
-			policy_cache_new(x);
-		CRYPTO_w_unlock(CRYPTO_LOCK_X509);
-		}
+		policy_cache_new(x);
+	cache = x->policy_cache;
+	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
 
-	return x->policy_cache;
-
+	return cache;
 	}
 
 X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 3f175c9..8ae8a06 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -67,6 +67,8 @@
 #include <openssl/x509_vfy.h>
 #include <openssl/x509v3.h>
 
+#include "../internal.h"
+
 
 static void x509v3_cache_extensions(X509 *x);
 
@@ -114,9 +116,7 @@
 	int idx;
 	const X509_PURPOSE *pt;
 	if(!(x->ex_flags & EXFLAG_SET)) {
-		CRYPTO_w_lock(CRYPTO_LOCK_X509);
 		x509v3_cache_extensions(x);
-		CRYPTO_w_unlock(CRYPTO_LOCK_X509);
 	}
 	if(id == -1) return 1;
 	idx = X509_PURPOSE_get_by_id(id);
@@ -367,6 +367,15 @@
 		setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
 	}
 
+/* g_x509_cache_extensions_lock is used to protect against concurrent calls to
+ * |x509v3_cache_extensions|. Ideally this would be done with a |CRYPTO_once_t|
+ * in the |X509| structure, but |CRYPTO_once_t| isn't public.
+ *
+ * Note: it's not entirely clear whether this lock is needed. Not all paths to
+ * this function took a lock in OpenSSL. */
+static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock =
+    CRYPTO_STATIC_MUTEX_INIT;
+
 static void x509v3_cache_extensions(X509 *x)
 {
 	BASIC_CONSTRAINTS *bs;
@@ -377,7 +386,15 @@
 	X509_EXTENSION *ex;
 	size_t i;
 	int j;
-	if(x->ex_flags & EXFLAG_SET) return;
+
+	CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
+
+	if(x->ex_flags & EXFLAG_SET)
+		{
+		CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+		return;
+		}
+
 	X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
 	/* V1 should mean no extensions ... */
 	if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
@@ -501,6 +518,8 @@
 			}
 		}
 	x->ex_flags |= EXFLAG_SET;
+
+	CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
 }
 
 /* CA checks common to all purposes
@@ -544,9 +563,7 @@
 int X509_check_ca(X509 *x)
 {
 	if(!(x->ex_flags & EXFLAG_SET)) {
-		CRYPTO_w_lock(CRYPTO_LOCK_X509);
 		x509v3_cache_extensions(x);
-		CRYPTO_w_unlock(CRYPTO_LOCK_X509);
 	}
 
 	return check_ca(x);