Thread-safety fixes
diff --git a/CHANGES b/CHANGES
index 33c9186..037c916 100644
--- a/CHANGES
+++ b/CHANGES
@@ -289,6 +289,10 @@
 
  Changes between 0.9.8b and 0.9.8c  [xx XXX xxxx]
 
+  *) Fix RSA blinding Heisenbug (problems sometimes occured on
+     dual-core machines) and other potential thread-safety issues.
+     [Bodo Moeller]
+
   *) Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key
      versions), which is now available for royalty-free use
      (see http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html).
@@ -389,6 +393,9 @@
 
  Changes between 0.9.7h and 0.9.8  [05 Jul 2005]
 
+  [NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after
+  OpenSSL 0.9.8.]
+
   *) Add libcrypto.pc and libssl.pc for those who feel they need them.
      [Richard Levitte]
 
@@ -1206,6 +1213,27 @@
      differing sizes.
      [Richard Levitte]
 
+ Changes between 0.9.7j and 0.9.7k  [xx XXX xxxx]
+
+  *) Fix RSA blinding Heisenbug (problems sometimes occured on
+     dual-core machines) and other potential thread-safety issues.
+     [Bodo Moeller]
+
+ Changes between 0.9.7i and 0.9.7j  [04 May 2006]
+
+  *) Adapt fipsld and the build system to link against the validated FIPS
+     module in FIPS mode.
+     [Steve Henson]
+
+  *) Fixes for VC++ 2005 build under Windows.
+     [Steve Henson]
+
+  *) Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make 
+     from a Windows bash shell such as MSYS. It is autodetected from the
+     "config" script when run from a VC++ environment. Modify standard VC++
+     build to use fipscanister.o from the GNU make build. 
+     [Steve Henson]
+
  Changes between 0.9.7h and 0.9.7i  [14 Oct 2005]
 
   *) Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS.
diff --git a/LICENSE b/LICENSE
index e6afecc..c21f132 100644
--- a/LICENSE
+++ b/LICENSE
@@ -12,7 +12,7 @@
   ---------------
 
 /* ====================================================================
- * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c
index c2cfecf..b532305 100644
--- a/crypto/bn/bn_mont.c
+++ b/crypto/bn/bn_mont.c
@@ -55,6 +55,59 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
 
 /*
  * Details about Montgomery multiplication algorithms can be found at
@@ -427,18 +480,30 @@
 BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
 					const BIGNUM *mod, BN_CTX *ctx)
 	{
-	if (*pmont)
-		return *pmont;
-	CRYPTO_w_lock(lock);
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(lock);
 	if (!*pmont)
 		{
-		BN_MONT_CTX *mtmp;
-		mtmp = BN_MONT_CTX_new();
-		if (mtmp && !BN_MONT_CTX_set(mtmp, mod, ctx))
-			BN_MONT_CTX_free(mtmp);
-		else
-			*pmont = mtmp;
+		CRYPTO_r_unlock(lock);
+		CRYPTO_w_lock(lock);
+		got_write_lock = 1;
+
+		if (!*pmont)
+			{
+			BN_MONT_CTX *mtmp;
+			mtmp = BN_MONT_CTX_new();
+			if (mtmp && !BN_MONT_CTX_set(mtmp, mod, ctx))
+				BN_MONT_CTX_free(mtmp);
+			else
+				*pmont = mtmp;
+			}
 		}
-	CRYPTO_w_unlock(lock);
+	
+	if (got_write_lock)
+		CRYPTO_w_unlock(lock);
+	else
+		CRYPTO_r_unlock(lock);
+		
 	return *pmont;
 	}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 8474132..3367a75 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -550,9 +550,20 @@
 	int i;
 	static int init = 1;
 
-	if (!init) return;
-
+	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+	if (!init)
+		{
+		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+		return;
+		}
+	
+	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (!init)
+		{
+		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+		return;
+		}
 
 	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
 		{
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 56da944..69cabd2 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -238,40 +238,63 @@
 	return(r);
 	}
 
-static BN_BLINDING *rsa_get_blinding(RSA *rsa, BIGNUM **r, int *local, BN_CTX *ctx)
+static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
 {
 	BN_BLINDING *ret;
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_RSA);
 
 	if (rsa->blinding == NULL)
 		{
+		CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+		CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+		got_write_lock = 1;
+
 		if (rsa->blinding == NULL)
-			{
-			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
-			if (rsa->blinding == NULL)
-				rsa->blinding = RSA_setup_blinding(rsa, ctx);
-			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-			}
+			rsa->blinding = RSA_setup_blinding(rsa, ctx);
 		}
 
 	ret = rsa->blinding;
 	if (ret == NULL)
-		return NULL;
+		goto err;
 
-	if (BN_BLINDING_get_thread_id(ret) != CRYPTO_thread_id())
+	if (BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id())
 		{
-		*local = 0;
+		/* rsa->blinding is ours! */
+
+		*local = 1;
+		}
+	else
+		{
+		/* resort to rsa->mt_blinding instead */
+
+		*local = 0; /* instructs rsa_blinding_convert(), rsa_blinding_invert()
+		             * that the BN_BLINDING is shared, meaning that accesses
+		             * require locks, and that the blinding factor must be
+		             * stored outside the BN_BLINDING
+		             */
+
 		if (rsa->mt_blinding == NULL)
 			{
-			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+			if (!got_write_lock)
+				{
+				CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+				CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+				got_write_lock = 1;
+				}
+			
 			if (rsa->mt_blinding == NULL)
 				rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
-			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
 			}
 		ret = rsa->mt_blinding;
 		}
-	else
-		*local = 1;
 
+ err:
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
 	return ret;
 }
 
@@ -358,7 +381,7 @@
 
 	if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
 		{
-		blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
+		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
 		if (blinding == NULL)
 			{
 			RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
@@ -479,7 +502,7 @@
 
 	if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
 		{
-		blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
+		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
 		if (blinding == NULL)
 			{
 			RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 452a082..fb08009 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -73,12 +73,12 @@
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
+ *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
@@ -87,7 +87,7 @@
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -102,6 +102,11 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
  */
 /* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
@@ -130,21 +135,28 @@
 int SSL_get_ex_data_X509_STORE_CTX_idx(void)
 	{
 	static volatile int ssl_x509_store_ctx_idx= -1;
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
 
 	if (ssl_x509_store_ctx_idx < 0)
 		{
-		/* any write lock will do; usually this branch
-		 * will only be taken once anyway */
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+		got_write_lock = 1;
 		
 		if (ssl_x509_store_ctx_idx < 0)
 			{
 			ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index(
 				0,"SSL for verify callback",NULL,NULL,NULL);
 			}
-		
-		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
 		}
+
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+	
 	return ssl_x509_store_ctx_idx;
 	}
 
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 6bf337b..5453037 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -56,6 +56,59 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  * ECC cipher suite support in OpenSSL originally developed by 
  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
@@ -243,36 +296,46 @@
 
 static void load_builtin_compressions(void)
 	{
-	if (ssl_comp_methods != NULL)
-		return;
+	int got_write_lock = 0;
 
-	CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+	CRYPTO_r_lock(CRYPTO_LOCK_SSL);
 	if (ssl_comp_methods == NULL)
 		{
-		SSL_COMP *comp = NULL;
-
-		MemCheck_off();
-		ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp);
-		if (ssl_comp_methods != NULL)
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL);
+		CRYPTO_w_lock(CRYPTO_LOCK_SSL);
+		got_write_lock = 1;
+		
+		if (ssl_comp_methods == NULL)
 			{
-			comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
-			if (comp != NULL)
+			SSL_COMP *comp = NULL;
+
+			MemCheck_off();
+			ssl_comp_methods=sk_SSL_COMP_new(sk_comp_cmp);
+			if (ssl_comp_methods != NULL)
 				{
-				comp->method=COMP_zlib();
-				if (comp->method
-					&& comp->method->type == NID_undef)
-					OPENSSL_free(comp);
-				else
+				comp=(SSL_COMP *)OPENSSL_malloc(sizeof(SSL_COMP));
+				if (comp != NULL)
 					{
-					comp->id=SSL_COMP_ZLIB_IDX;
-					comp->name=comp->method->name;
-					sk_SSL_COMP_push(ssl_comp_methods,comp);
+					comp->method=COMP_zlib();
+					if (comp->method
+						&& comp->method->type == NID_undef)
+						OPENSSL_free(comp);
+					else
+						{
+						comp->id=SSL_COMP_ZLIB_IDX;
+						comp->name=comp->method->name;
+						sk_SSL_COMP_push(ssl_comp_methods,comp);
+						}
 					}
 				}
+			MemCheck_on();
 			}
-		MemCheck_on();
 		}
-	CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+	
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_SSL);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_SSL);
 	}
 #endif