clean up new code for NIST primes

create new lock CRYPTO_LOCK_BN to avoid race condition
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 21a1a90..2f203fe 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -547,14 +547,6 @@
 		} \
 	}
 
-#define bn_clear_top2max(a) \
-	{ \
-	int      index = (a)->dmax - (a)->top; \
-	BN_ULONG *ftl = &(a)->d[(a)->top-1]; \
-	for (; index != 0; index--) \
-		*(++ftl) = 0x0; \
-	}
-
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
 BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
 void     bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h
index 8a4dba3..090a7a0 100644
--- a/crypto/bn/bn_lcl.h
+++ b/crypto/bn/bn_lcl.h
@@ -239,6 +239,16 @@
 #define Lw(t)    (((BN_ULONG)(t))&BN_MASK2)
 #define Hw(t)    (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
 
+
+#define bn_clear_top2max(a) \
+	{ \
+	int      index = (a)->dmax - (a)->top; \
+	BN_ULONG *ftl = &(a)->d[(a)->top-1]; \
+	for (; index != 0; index--) \
+		*(++ftl) = 0x0; \
+	}
+
+
 /* This is used for internal error checking and is not normally used */
 #ifdef BN_DEBUG
 # include <assert.h>
diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c
index 4e21a05..19bd540 100644
--- a/crypto/bn/bn_nist.c
+++ b/crypto/bn/bn_nist.c
@@ -54,11 +54,12 @@
  */
 
 #include "bn_lcl.h"
+#include "cryptlib.h"
 
 #define BN_NIST_192_TOP	(192+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_224_TOP	(224+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_256_TOP	(256+BN_BITS2-1)/BN_BITS2
-#define	BN_NIST_384_TOP	(384+BN_BITS2-1)/BN_BITS2
+#define BN_NIST_384_TOP	(384+BN_BITS2-1)/BN_BITS2
 #define BN_NIST_521_TOP	(521+BN_BITS2-1)/BN_BITS2
 
 #if BN_BITS2 == 64
@@ -314,7 +315,7 @@
 	if (top == 0)
 		return BN_zero(r);
 	else if (top > 0)
-		return (r == a)? 1 : !!BN_copy(r ,a);
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
 	if (r != a)
 		if (!BN_ncopy(r, a, BN_NIST_192_TOP))
@@ -353,7 +354,7 @@
 		}
 	r->top = BN_NIST_192_TOP;
 
-#if 0
+#if 1
 	bn_clear_top2max(r);
 #endif
 	bn_fix_top(r);
@@ -393,7 +394,7 @@
 	if (tmp_int == 0)
 		return BN_zero(r);
 	else if (tmp_int > 0)
-		return (r == a)? 1 : !!BN_copy(r ,a);
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
 	if (r != a)
 		if (!BN_ncopy(r, a, BN_NIST_224_TOP))
@@ -445,7 +446,7 @@
 			}
 
 	r->top = BN_NIST_224_TOP;
-#if 0
+#if 1
 	bn_clear_top2max(r);
 #endif
 	bn_fix_top(r);
@@ -503,13 +504,20 @@
 	BN_32_BIT_BUF(14) BN_32_BIT_BUF(15)
 
 	if (!_is_set_256_data)
-		_init_256_data();
-
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_BN);
+		
+		if (!_is_set_256_data)
+			_init_256_data();
+		
+		CRYPTO_w_unlock(CRYPTO_LOCK_BN);
+		}
+	
 	tmp_int = BN_ucmp(field, a);
 	if (tmp_int == 0)
 		return BN_zero(r);
 	else if (tmp_int > 0)
-		return (r == a)? 1 : !!BN_copy(r ,a);
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
 	if (r != a)
 		if (!BN_ncopy(r, a, BN_NIST_256_TOP))
@@ -596,7 +604,7 @@
 		}
 
 	r->top = BN_NIST_256_TOP;
-#if 0
+#if 1
 	bn_clear_top2max(r);
 #endif
 	bn_fix_top(r);
@@ -657,13 +665,20 @@
 	BN_32_BIT_BUF(22) BN_32_BIT_BUF(23)
 
 	if (!_is_set_384_data)
-		_init_384_data();
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_BN);
+		
+		if (!_is_set_384_data)
+			_init_384_data();
+
+		CRYPTO_w_unlock(CRYPTO_LOCK_BN);
+		}
 
 	tmp_int = BN_ucmp(field, a);
 	if (tmp_int == 0)
 		return BN_zero(r);
 	else if (tmp_int > 0)
-		return (r == a)? 1 : !!BN_copy(r ,a);
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
 	if (r != a)
 		if (!BN_ncopy(r, a, BN_NIST_384_TOP))
@@ -757,7 +772,7 @@
 		}
 
 	r->top = BN_NIST_384_TOP;
-#if 0
+#if 1
 	bn_clear_top2max(r);
 #endif
 	bn_fix_top(r);
@@ -793,7 +808,7 @@
 	top = a->top;
 	if (top < BN_NIST_521_TOP  || ( top == BN_NIST_521_TOP &&
            (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))))
-		return (r == a)? 1 : !!BN_copy(r ,a);
+		return (r == a)? 1 : (BN_copy(r ,a) != NULL);
 
 	BN_CTX_start(ctx);
 	tmp = BN_CTX_get(ctx);
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
index 5d8debd..e16bbc6 100644
--- a/crypto/cryptlib.c
+++ b/crypto/cryptlib.c
@@ -1,4 +1,57 @@
 /* crypto/cryptlib.c */
+/* ====================================================================
+ * Copyright (c) 1998-2002 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 (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -112,7 +165,8 @@
 	"ecdsa",
 	"ec",
 	"ecdh",
-#if CRYPTO_NUM_LOCKS != 35
+	"bn",
+#if CRYPTO_NUM_LOCKS != 36
 # error "Inconsistency between crypto.h and cryptlib.c"
 #endif
 	};
diff --git a/crypto/crypto.h b/crypto/crypto.h
index 1490db9..f87262f 100644
--- a/crypto/crypto.h
+++ b/crypto/crypto.h
@@ -1,4 +1,57 @@
 /* crypto/crypto.h */
+/* ====================================================================
+ * Copyright (c) 1998-2002 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 (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -135,7 +188,8 @@
 #define CRYPTO_LOCK_ECDSA               32
 #define CRYPTO_LOCK_EC			33
 #define CRYPTO_LOCK_ECDH		34
-#define CRYPTO_NUM_LOCKS		35
+#define CRYPTO_LOCK_BN  		35
+#define CRYPTO_NUM_LOCKS		36
 
 #define CRYPTO_LOCK		1
 #define CRYPTO_UNLOCK		2
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h
index 5abef25..1cd6d34 100644
--- a/crypto/ec/ec.h
+++ b/crypto/ec/ec.h
@@ -486,6 +486,8 @@
 #define EC_R_INVALID_PRIVATE_KEY			 123
 #define EC_R_MISSING_PARAMETERS				 124
 #define EC_R_MISSING_PRIVATE_KEY			 125
+#define EC_R_NOT_A_NIST_PRIME			         135
+#define EC_R_NOT_A_SUPPORTED_NIST_PRIME	                 136
 #define EC_R_NOT_IMPLEMENTED				 126
 #define EC_R_NOT_INITIALIZED				 111
 #define EC_R_NO_FIELD_MOD				 133
@@ -494,7 +496,6 @@
 #define EC_R_PKPARAMETERS2GROUP_FAILURE			 127
 #define EC_R_POINT_AT_INFINITY				 106
 #define EC_R_POINT_IS_NOT_ON_CURVE			 107
-#define EC_R_PRIME_IS_NOT_A_NIST_PRIME			 135
 #define EC_R_SLOT_FULL					 108
 #define EC_R_UNDEFINED_GENERATOR			 113
 #define EC_R_UNDEFINED_ORDER				 128
diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c
index 2078256..7571a3c 100644
--- a/crypto/ec/ec_cvt.c
+++ b/crypto/ec/ec_cvt.c
@@ -99,9 +99,25 @@
 
 	if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
 		{
-		/* remove the last error code form the error queue */
-		ERR_get_error();
-		/* try the normal mont method */
+		unsigned long err;
+		  
+		err = ERR_peek_last_error();
+
+		if (!(ERR_GET_LIB(err) == ERR_LIB_EC &&
+			((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) ||
+			 (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME))))
+			{
+			/* real error */
+			
+			EC_GROUP_clear_free(ret);
+			return NULL;
+			}
+			
+		
+		/* not an actual error, we just cannot use EC_GFp_nist_method */
+
+		ERR_clear_error();
+
 		EC_GROUP_clear_free(ret);
 		meth = EC_GFp_mont_method();
 
@@ -119,6 +135,7 @@
 	return ret;
 	}
 
+
 EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 	{
 	const EC_METHOD *meth;
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 71b1dcf..58ae9d6 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -195,6 +195,8 @@
 {EC_R_INVALID_PRIVATE_KEY                ,"invalid private key"},
 {EC_R_MISSING_PARAMETERS                 ,"missing parameters"},
 {EC_R_MISSING_PRIVATE_KEY                ,"missing private key"},
+{EC_R_NOT_A_NIST_PRIME                   ,"not a NIST prime"},
+{EC_R_NOT_A_SUPPORTED_NIST_PRIME         ,"not a supported NIST prime"},
 {EC_R_NOT_IMPLEMENTED                    ,"not implemented"},
 {EC_R_NOT_INITIALIZED                    ,"not initialized"},
 {EC_R_NO_FIELD_MOD                       ,"no field mod"},
@@ -203,7 +205,6 @@
 {EC_R_PKPARAMETERS2GROUP_FAILURE         ,"pkparameters2group failure"},
 {EC_R_POINT_AT_INFINITY                  ,"point at infinity"},
 {EC_R_POINT_IS_NOT_ON_CURVE              ,"point is not on curve"},
-{EC_R_PRIME_IS_NOT_A_NIST_PRIME          ,"prime is not a nist prime"},
 {EC_R_SLOT_FULL                          ,"slot full"},
 {EC_R_UNDEFINED_GENERATOR                ,"undefined generator"},
 {EC_R_UNDEFINED_ORDER                    ,"undefined order"},
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index 247c985..639d174 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -227,6 +227,7 @@
 
 	void *field_data1; /* method-specific (e.g., Montgomery structure) */
 	void *field_data2; /* method-specific */
+	int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,	BN_CTX *); /* method-specific */
 } /* EC_GROUP */;
 
 
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 3c2b4fa..fb43510 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -109,9 +109,6 @@
 	return &ret;
 	}
 
-#define	ECP_MOD_CAST	\
-	(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *))
-
 #if BN_BITS2 == 64 && UINT_MAX != 4294967295UL && ULONG_MAX != 4294967295UL
 #define	NO_32_BIT_TYPE
 #endif
@@ -155,31 +152,34 @@
 	if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err;
 
 	if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
-		group->field_data1 = (void *)BN_nist_mod_192;
+		group->field_mod_func = BN_nist_mod_192;
 	else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
-#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
-		group->field_data1 = (void *)BN_nist_mod_224;
+#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
+		group->field_mod_func = BN_nist_mod_224;
 #else
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
 		goto err;
 #endif
 	else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
-#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
-		group->field_data1 = (void *)BN_nist_mod_256;
+#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
+		group->field_mod_func = BN_nist_mod_256;
 #else
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
 		goto err;
 #endif
 	else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
-#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
-		group->field_data1 = (void *)BN_nist_mod_384;
+#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM)
+		group->field_mod_func = BN_nist_mod_384;
 #else
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
 		goto err;
 #endif
 	else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
-		group->field_data1 = (void *)BN_nist_mod_521;
+		/* this one works in the NO_32_BIT_TYPE case */
+		group->field_mod_func = BN_nist_mod_521;
 	else
 		{
-		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, 
-			EC_R_PRIME_IS_NOT_A_NIST_PRIME);
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_NIST_PRIME);
 		goto err;
 		}
 
@@ -188,10 +188,10 @@
 	group->field.neg = 0;
 
 	/* group->a */
-	(ECP_MOD_CAST group->field_data1)(&group->a, a, p, ctx);
+	if (!group->field_mod_func(&group->a, a, p, ctx)) goto err;
 
 	/* group->b */
-	(ECP_MOD_CAST group->field_data1)(&group->b, b, p, ctx);
+	if (!group->field_mod_func(&group->b, b, p, ctx)) goto err;
 
 	/* group->a_is_minus3 */
 	if (!BN_add_word(tmp_bn, 3)) goto err;
@@ -242,7 +242,7 @@
 		if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
 
 	if (!BN_mul(r, a, b, ctx)) goto err;
-	if (!(ECP_MOD_CAST group->field_data1)(r, r, &group->field, ctx))
+	if (!group->field_mod_func(r, r, &group->field, ctx))
 		goto err;
 
 	ret=1;
@@ -267,7 +267,7 @@
 		if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
 
 	if (!BN_sqr(r, a, ctx)) goto err;
-	if (!(ECP_MOD_CAST group->field_data1)(r, r, &group->field, ctx))
+	if (!group->field_mod_func(r, r, &group->field, ctx))
 		goto err;
 
 	ret=1;