fast reduction for NIST curves

Submitted by: Nils Larsch
diff --git a/CHANGES b/CHANGES
index c211f4b..c22b945 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 0.9.7 and 0.9.8  [xx XXX 2002]
 
+  *) Implement fast modular reduction for pseudo-Mersenne primes
+     used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c).
+     EC_GROUP_new_curve_GFp() will now automatically use this
+     if applicable.
+     [Nils Larsch <nla@trustcenter.de>]
+
   *) Change the ENGINE framework to automatically load engines
      dynamically from specific directories unless they could be
      found to already be built in or loaded.  Move all the
diff --git a/apps/speed.c b/apps/speed.c
index a8a375f..ac643bd 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -261,7 +261,7 @@
 #define RSA_NUM		4
 #define DSA_NUM		3
 
-#define EC_NUM       15
+#define EC_NUM       16
 #define MAX_ECDH_SIZE 256
 
 static const char *names[ALGOR_NUM]={
@@ -520,20 +520,21 @@
 #define	R_RSA_4096	3
 
 #define R_EC_P160    0
-#define R_EC_P224    1
-#define R_EC_P256    2
-#define R_EC_P384    3
-#define R_EC_P521    4
-#define R_EC_K163    5
-#define R_EC_K233    6
-#define R_EC_K283    7
-#define R_EC_K409    8
-#define R_EC_K571    9
-#define R_EC_B163    10
-#define R_EC_B233    11
-#define R_EC_B283    12
-#define R_EC_B409    13
-#define R_EC_B571    14
+#define R_EC_P192    1	
+#define R_EC_P224    2
+#define R_EC_P256    3
+#define R_EC_P384    4
+#define R_EC_P521    5
+#define R_EC_K163    6
+#define R_EC_K233    7
+#define R_EC_K283    8
+#define R_EC_K409    9
+#define R_EC_K571    10
+#define R_EC_B163    11
+#define R_EC_B233    12
+#define R_EC_B283    13
+#define R_EC_B409    14
+#define R_EC_B571    15
 
 #ifndef OPENSSL_NO_RSA
 	RSA *rsa_key[RSA_NUM];
@@ -560,6 +561,7 @@
 	{	
 	/* Prime Curves */
 	NID_secp160r1,
+	NID_X9_62_prime192v1,
 	NID_secp224r1,
 	NID_X9_62_prime256v1,
 	NID_secp384r1,
@@ -580,6 +582,7 @@
 	{
 	/* Prime Curves */
 	"secp160r1",
+	"nistp192",
 	"nistp224",
 	"nistp256",
 	"nistp384",
@@ -598,7 +601,7 @@
 	};
 	static int test_curves_bits[EC_NUM] =
         {
-        160, 224, 256, 384, 521,
+        160, 192, 224, 256, 384, 521,
         163, 233, 283, 409, 571,
         163, 233, 283, 409, 571
         };
diff --git a/crypto/bn/Makefile.ssl b/crypto/bn/Makefile.ssl
index e54f066..54a3ead 100644
--- a/crypto/bn/Makefile.ssl
+++ b/crypto/bn/Makefile.ssl
@@ -39,12 +39,12 @@
 LIBSRC=	bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \
 	bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
 	bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c bn_asm.c \
-	bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c
+	bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c
 
 LIBOBJ=	bn_add.o bn_div.o bn_exp.o bn_lib.o bn_ctx.o bn_mul.o bn_mod.o \
 	bn_print.o bn_rand.o bn_shift.o bn_word.o bn_blind.o \
 	bn_kron.o bn_sqrt.o bn_gcd.o bn_prime.o bn_err.o bn_sqr.o $(BN_ASM) \
-	bn_recp.o bn_mont.o bn_mpi.o bn_exp2.o bn_gf2m.o
+	bn_recp.o bn_mont.o bn_mpi.o bn_exp2.o bn_gf2m.o bn_nist.o
 
 SRC= $(LIBSRC)
 
@@ -286,6 +286,8 @@
 bn_mul.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h
 bn_mul.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
 bn_mul.o: ../cryptlib.h bn_lcl.h bn_mul.c
+bn_nist.o: ../../include/openssl/bn.h ../../include/openssl/e_os2.h
+bn_nist.o: ../../include/openssl/opensslconf.h bn_lcl.h bn_nist.c
 bn_prime.o: ../../e_os.h ../../include/openssl/bio.h ../../include/openssl/bn.h
 bn_prime.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
 bn_prime.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 1170465..21a1a90 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -355,6 +355,8 @@
 void	BN_init(BIGNUM *);
 void	BN_clear_free(BIGNUM *a);
 BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
+/* BN_ncopy(): like BN_copy() but copies at most the first n BN_ULONGs */
+BIGNUM *BN_ncopy(BIGNUM *a, const BIGNUM *b, size_t n);
 void	BN_swap(BIGNUM *a, BIGNUM *b);
 BIGNUM *BN_bin2bn(const unsigned char *s,int len,BIGNUM *ret);
 int	BN_bn2bin(const BIGNUM *a, unsigned char *to);
@@ -513,6 +515,20 @@
 int BN_GF2m_poly2arr(const BIGNUM *a, unsigned int p[], int max);
 int BN_GF2m_arr2poly(const unsigned int p[], BIGNUM *a);
 
+/* faster mod functions for the 'NIST primes' 
+ * 0 <= a < p^2 */
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
+const BIGNUM *BN_get0_nist_prime_192(void);
+const BIGNUM *BN_get0_nist_prime_224(void);
+const BIGNUM *BN_get0_nist_prime_256(void);
+const BIGNUM *BN_get0_nist_prime_384(void);
+const BIGNUM *BN_get0_nist_prime_521(void);
+
 /* library internal functions */
 
 #define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
@@ -531,6 +547,14 @@
 		} \
 	}
 
+#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_lib.c b/crypto/bn/bn_lib.c
index 20f851c..fc610e0 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -522,6 +522,51 @@
 	return(a);
 	}
 
+BIGNUM *BN_ncopy(BIGNUM *a, const BIGNUM *b, size_t n)
+	{
+	int i, min;
+	BN_ULONG *A;
+	const BN_ULONG *B;
+
+	bn_check_top(b);
+
+	if (a == b)
+		return a;
+
+	min = (b->top < (int)n)? b->top: (int)n;
+
+	if (!min)
+		{
+		BN_zero(a);
+		return a;
+		}
+
+	if (bn_wexpand(a, min) == NULL)
+		return NULL;
+
+	A=a->d;
+	B=b->d;
+	for (i=min>>2; i>0; i--, A+=4, B+=4)
+		{
+		BN_ULONG a0,a1,a2,a3;
+		a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3];
+		A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3;
+		}
+	switch (min&3)
+		{
+		case 3: A[2]=B[2];
+		case 2: A[1]=B[1];
+		case 1: A[0]=B[0];
+		case 0: ;
+		}
+	a->top = min;
+
+	a->neg = b->neg;
+	bn_fix_top(a);
+
+	return(a);
+	}
+
 void BN_swap(BIGNUM *a, BIGNUM *b)
 	{
 	int flags_old_a, flags_old_b;
diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c
new file mode 100644
index 0000000..4e21a05
--- /dev/null
+++ b/crypto/bn/bn_nist.c
@@ -0,0 +1,828 @@
+/* crypto/bn/bn_nist.p */
+/* ====================================================================
+ * 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).
+ *
+ */
+
+#include "bn_lcl.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_521_TOP	(521+BN_BITS2-1)/BN_BITS2
+
+#if BN_BITS2 == 64
+const static BN_ULONG _nist_p_192[] = {0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFE,
+	0xFFFFFFFFFFFFFFFF};
+const static BN_ULONG _nist_p_224[] = {0x0000000000000001,0xFFFFFFFF00000000,
+	0xFFFFFFFFFFFFFFFF,0x00000000FFFFFFFF};
+const static BN_ULONG _nist_p_256[] = {0xFFFFFFFFFFFFFFFF,0x00000000FFFFFFFF,
+	0x0000000000000000,0xFFFFFFFF00000001};
+const static BN_ULONG _nist_p_384[] = {0x00000000FFFFFFFF,0xFFFFFFFF00000000,
+	0xFFFFFFFFFFFFFFFE,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,
+	0xFFFFFFFFFFFFFFFF};
+const static BN_ULONG _nist_p_521[] = {0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,
+	0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,
+	0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFFFF,
+	0x00000000000001FF};
+#elif BN_BITS2 == 32
+const static BN_ULONG _nist_p_192[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+const static BN_ULONG _nist_p_224[] = {0x00000001,0x00000000,0x00000000,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+const static BN_ULONG _nist_p_256[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0x00000000,0x00000000,0x00000000,0x00000001,0xFFFFFFFF};
+const static BN_ULONG _nist_p_384[] = {0xFFFFFFFF,0x00000000,0x00000000,
+	0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+const static BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
+	0xFFFFFFFF,0x000001FF};
+#elif BN_BITS2 == 16
+const static BN_ULONG _nist_p_192[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFE,
+	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
+const static BN_ULONG _nist_p_224[] = {0x0001,0x0000,0x0000,0x0000,0x0000,
+	0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
+const static BN_ULONG _nist_p_256[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+	0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x0000,0xFFFF,
+	0xFFFF};
+const static BN_ULONG _nist_p_384[] = {0xFFFF,0xFFFF,0x0000,0x0000,0x0000,
+	0x0000,0xFFFF,0xFFFF,0xFFFE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
+const static BN_ULONG _nist_p_521[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
+	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x01FF};
+#elif BN_BITS2 == 8
+const static BN_ULONG _nist_p_192[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF};
+const static BN_ULONG _nist_p_224[] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+const static BN_ULONG _nist_p_256[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
+const static BN_ULONG _nist_p_384[] = {0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
+	0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+const static BN_ULONG _nist_p_521[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	0xFF,0x01};
+#endif
+
+const BIGNUM *BN_get0_nist_prime_192(void)
+	{
+	static BIGNUM const_nist_192={(BN_ULONG *)_nist_p_192,BN_NIST_192_TOP,
+		BN_NIST_192_TOP, 0, BN_FLG_STATIC_DATA};
+	return &const_nist_192;
+	}
+
+const BIGNUM *BN_get0_nist_prime_224(void)
+	{
+	static BIGNUM const_nist_224={(BN_ULONG *)_nist_p_224,BN_NIST_224_TOP,
+		BN_NIST_224_TOP, 0, BN_FLG_STATIC_DATA};
+	return &const_nist_224;
+	}
+
+const BIGNUM *BN_get0_nist_prime_256(void)
+	{
+	static BIGNUM const_nist_256={(BN_ULONG *)_nist_p_256,BN_NIST_256_TOP,
+		BN_NIST_256_TOP, 0, BN_FLG_STATIC_DATA};
+	return &const_nist_256;
+	}
+
+const BIGNUM *BN_get0_nist_prime_384(void)
+	{
+	static BIGNUM const_nist_384={(BN_ULONG *)_nist_p_384,BN_NIST_384_TOP,
+		BN_NIST_384_TOP, 0, BN_FLG_STATIC_DATA};
+	return &const_nist_384;
+	}
+
+const BIGNUM *BN_get0_nist_prime_521(void)
+	{
+	static BIGNUM const_nist_521={(BN_ULONG *)_nist_p_521,BN_NIST_521_TOP,
+		BN_NIST_521_TOP, 0, BN_FLG_STATIC_DATA};
+	return &const_nist_521;
+	}
+
+/* some misc internal functions */
+static BN_ULONG _256_data[BN_NIST_256_TOP*6];
+static int _is_set_256_data = 0;
+static void _init_256_data(void);
+
+static BN_ULONG _384_data[BN_NIST_384_TOP*8];
+static int _is_set_384_data = 0;
+static void _init_384_data(void);
+
+#define BN_NIST_ADD_ONE(a)	while (!(++(*(a)))) ++(a);
+#define __buf_0			(BN_ULONG)0
+#define __buf_0_1		(BN_ULONG)0
+#define __buf_0_2		(BN_ULONG)0
+#if BN_BITS2 == 64
+#define BN_64_BIT_BUF(n)	BN_ULONG __buf_##n = (BN_ULONG)0;
+#define BN_CP_64_TO_BUF(n)	__buf_##n = (a)[(n)];
+#define BN_CP_64_FROM_BUF(a,n)	*(a)++ = __buf_##n;
+#define BN_CASE_64_BIT(n,a)	case (n): __buf_##n = (a)[(n)];
+#if	UINT_MAX == 4294967295UL
+#define	nist32	unsigned int
+#define BN_32_BIT_BUF(n)	nist32 __buf_##n = (nist32)0;
+#define BN_CP_32_TO_BUF(n)	__buf_##n = ((nist32 *)(a))[(n)];
+#define BN_CP_32_FROM_BUF(a,n)	*((nist32)(a))++ = __buf_##n;
+#define BN_CASE_32_BIT(n,a)	case (n): __buf_##n = ((nist32)(a))[(n)];
+#elif	ULONG_MAX == 4294967295UL
+#define	nist32	unsigned long
+#define BN_32_BIT_BUF(n)	nist32 __buf_##n = (nist32)0;
+#define BN_CP_32_TO_BUF(n)	__buf_##n = ((nist32 *)(a))[(n)];
+#define BN_CP_32_FROM_BUF(a,n)	*((nist32)(a))++ = __buf_##n;
+#define BN_CASE_32_BIT(n,a)	case (n): __buf_##n = ((nist32)(a))[(n)];
+#else
+#define	NO_32_BIT_TYPE
+#endif
+#elif BN_BITS2 == 32
+#define BN_64_BIT_BUF(n)	BN_ULONG __buf_##n##_1 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_2 = (BN_ULONG)0;
+#define BN_CP_64_TO_BUF(n)	__buf_##n##_2 = (a)[2*(n)+1];\
+				__buf_##n##_1 = (a)[2*(n)];
+#define BN_CP_64_FROM_BUF(a,n)	*(a)++ = __buf_##n##_1;\
+				*(a)++ = __buf_##n##_2;
+#define BN_CASE_64_BIT(n,a)	case 2*(n)+1: __buf_##n##_2 = (a)[2*(n)+1];\
+				case 2*(n):   __buf_##n##_1 = (a)[2*(n)];
+				
+#define BN_32_BIT_BUF(n)	BN_ULONG __buf_##n = (BN_ULONG)0;
+#define BN_CP_32_TO_BUF(n)	__buf_##n = (a)[(n)];
+#define BN_CP_32_FROM_BUF(a,n)	*(a)++ = __buf_##n;
+#define BN_CASE_32_BIT(n,a)	case (n): __buf_##n = (a)[(n)];
+#elif BN_BITS2 == 16
+#define __buf_0_3		(BN_ULONG)0
+#define __buf_0_4		(BN_ULONG)0
+#define BN_64_BIT_BUF(n)	BN_ULONG __buf_##n##_1 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_2 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_3 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_4 = (BN_ULONG)0;
+#define BN_CP_64_TO_BUF(n)	__buf_##n##_4 = (a)[4*(n)+3];\
+				__buf_##n##_3 = (a)[4*(n)+2];\
+				__buf_##n##_2 = (a)[4*(n)+1];\
+				__buf_##n##_1 = (a)[4*(n)];
+#define BN_CP_64_FROM_BUF(a,n)	*(a)++ = __buf_##n##_1;\
+				*(a)++ = __buf_##n##_2;\
+				*(a)++ = __buf_##n##_3;\
+				*(a)++ = __buf_##n##_4;
+#define BN_CASE_64_BIT(n,a)	case 4*(n)+3: __buf_##n##_4 = (a)[4*(n)+3];\
+				case 4*(n)+2: __buf_##n##_3 = (a)[4*(n)+2];\
+				case 4*(n)+1: __buf_##n##_2 = (a)[4*(n)+1];\
+				case 4*(n):   __buf_##n##_1 = (a)[4*(n)];
+#define BN_32_BIT_BUF(n)	BN_ULONG __buf_##n##_1 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_2 = (BN_ULONG)0;
+#define BN_CP_32_TO_BUF(n)	__buf_##n##_1 = (a)[2*(n)];\
+				__buf_##n##_2 = (a)[2*(n)+1];
+#define BN_CP_32_FROM_BUF(a,n)	*(a)++ = __buf_##n##_1;\
+				*(a)++ = __buf_##n##_2;
+#define BN_CASE_32_BIT(n,a)	case 2*(n)+1: __buf_##n##_2 = (a)[2*(n)+1];\
+				case 2*(n):   __buf_##n##_1 = (a)[2*(n)];
+#elif BN_BITS2 == 8
+#define __buf_0_3		(BN_ULONG)0
+#define __buf_0_4		(BN_ULONG)0
+#define __buf_0_5		(BN_ULONG)0
+#define __buf_0_6		(BN_ULONG)0
+#define __buf_0_7		(BN_ULONG)0
+#define __buf_0_8		(BN_ULONG)0
+#define BN_64_BIT_BUF(n)	BN_ULONG __buf_##n##_1 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_2 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_3 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_4 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_5 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_6 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_7 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_8 = (BN_ULONG)0;
+#define BN_CP_64_TO_BUF(n)	__buf_##n##_8 = (a)[8*(n)+7];\
+				__buf_##n##_7 = (a)[8*(n)+6];\
+				__buf_##n##_6 = (a)[8*(n)+5];\
+				__buf_##n##_5 = (a)[8*(n)+4];\
+				__buf_##n##_4 = (a)[8*(n)+3];\
+				__buf_##n##_3 = (a)[8*(n)+2];\
+				__buf_##n##_2 = (a)[8*(n)+1];\
+				__buf_##n##_1 = (a)[8*(n)];
+#define BN_CP_64_FROM_BUF(a,n)	*(a)++ = __buf_##n##_1;\
+				*(a)++ = __buf_##n##_2;\
+				*(a)++ = __buf_##n##_3;\
+				*(a)++ = __buf_##n##_4;\
+				*(a)++ = __buf_##n##_5;\
+				*(a)++ = __buf_##n##_6;\
+				*(a)++ = __buf_##n##_7;\
+				*(a)++ = __buf_##n##_8;
+#define BN_CASE_64_BIT(n,a)	case 8*(n)+7: __buf_##n##_8 = (a)[8*(n)+7];\
+				case 8*(n)+6: __buf_##n##_7 = (a)[8*(n)+6];\
+				case 8*(n)+5: __buf_##n##_6 = (a)[8*(n)+5];\
+				case 8*(n)+4: __buf_##n##_5 = (a)[8*(n)+4];\
+				case 8*(n)+3: __buf_##n##_4 = (a)[8*(n)+3];\
+				case 8*(n)+2: __buf_##n##_3 = (a)[8*(n)+2];\
+				case 8*(n)+1: __buf_##n##_2 = (a)[8*(n)+1];\
+				case 8*(n):   __buf_##n##_1 = (a)[8*(n)];
+#define BN_32_BIT_BUF(n)	BN_ULONG __buf_##n##_1 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_2 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_3 = (BN_ULONG)0;\
+				BN_ULONG __buf_##n##_4 = (BN_ULONG)0;
+#define BN_CP_32_TO_BUF(n)	__buf_##n##_1 = (a)[4*(n)];\
+				__buf_##n##_2 = (a)[4*(n)+1];\
+				__buf_##n##_3 = (a)[4*(n)+2];\
+				__buf_##n##_4 = (a)[4*(n)+3];
+#define BN_CP_32_FROM_BUF(a,n)	*(a)++ = __buf_##n##_1;\
+				*(a)++ = __buf_##n##_2;\
+				*(a)++ = __buf_##n##_3;\
+				*(a)++ = __buf_##n##_4;
+#define BN_CASE_32_BIT(n,a)	case 4*(n)+3: __buf_##n##_4 = (a)[4*(n)+3];\
+				case 4*(n)+2: __buf_##n##_3 = (a)[4*(n)+2];\
+				case 4*(n)+1: __buf_##n##_2 = (a)[4*(n)+1];\
+				case 4*(n):   __buf_##n##_1 = (a)[4*(n)];
+#endif
+
+
+#define BN_192_SET(d,a1,a2,a3) \
+	{\
+	register BN_ULONG *td = (d);\
+	BN_CP_64_FROM_BUF(td,a3); BN_CP_64_FROM_BUF(td,a2);\
+	BN_CP_64_FROM_BUF(td,a1);\
+	}
+
+int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
+	BN_CTX *ctx)
+	{
+	int      top;
+	BN_ULONG carry = 0;
+	register BN_ULONG *r_d, *a_d;
+	BN_ULONG t_d[BN_NIST_192_TOP];
+	BN_64_BIT_BUF(3)  BN_64_BIT_BUF(4)
+	BN_64_BIT_BUF(5)
+
+	top = BN_ucmp(field, a);
+	if (top == 0)
+		return BN_zero(r);
+	else if (top > 0)
+		return (r == a)? 1 : !!BN_copy(r ,a);
+
+	if (r != a)
+		if (!BN_ncopy(r, a, BN_NIST_192_TOP))
+			return 0;
+
+	r_d = r->d;
+	a_d = a->d;
+	top = a->top-1;
+
+	switch (top)
+		{
+		BN_CASE_64_BIT(5, a_d)
+		BN_CASE_64_BIT(4, a_d)
+		BN_CASE_64_BIT(3, a_d)
+			break;
+		default: /* a->top == field->top */
+			return BN_usub(r, a, field);
+		}
+
+	BN_192_SET(t_d,0,3,3)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
+		++carry;
+
+	BN_192_SET(t_d,4,4,0)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
+		++carry;
+
+	BN_192_SET(t_d,5,5,5)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
+		++carry;
+
+	while (carry)
+		{
+		if (bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP))
+			--carry; 
+		}
+	r->top = BN_NIST_192_TOP;
+
+#if 0
+	bn_clear_top2max(r);
+#endif
+	bn_fix_top(r);
+
+	if (BN_ucmp(r, field) >= 0)
+		{
+		bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP);
+		bn_fix_top(r);
+		}
+
+	return 1;
+	}
+
+#define BN_224_SET(d,a1,a2,a3,a4,a5,a6,a7) \
+	{\
+	register BN_ULONG *td = (d);\
+	BN_CP_32_FROM_BUF(td,a7); BN_CP_32_FROM_BUF(td,a6);\
+	BN_CP_32_FROM_BUF(td,a5); BN_CP_32_FROM_BUF(td,a4);\
+	BN_CP_32_FROM_BUF(td,a3); BN_CP_32_FROM_BUF(td,a2);\
+	BN_CP_32_FROM_BUF(td,a1);\
+	}
+
+int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
+	BN_CTX *ctx)
+	{
+#ifndef NO_32_BIT_TYPE
+	int	tmp_int;
+	int	carry = 0;
+	BN_ULONG *r_d, *a_d;
+	BN_ULONG t_d[BN_NIST_224_TOP];
+	BN_32_BIT_BUF(7)  BN_32_BIT_BUF(8)
+	BN_32_BIT_BUF(9)  BN_32_BIT_BUF(10)
+	BN_32_BIT_BUF(11) BN_32_BIT_BUF(12)
+	BN_32_BIT_BUF(13)
+
+	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);
+
+	if (r != a)
+		if (!BN_ncopy(r, a, BN_NIST_224_TOP))
+			return 0;
+
+	r_d = r->d;
+	a_d = a->d;
+
+	tmp_int = a->top-1;
+
+	switch (tmp_int)
+		{
+		BN_CASE_32_BIT(13, a_d)
+		BN_CASE_32_BIT(12, a_d)
+		BN_CASE_32_BIT(11, a_d)
+		BN_CASE_32_BIT(10, a_d)
+		BN_CASE_32_BIT(9,  a_d)
+		BN_CASE_32_BIT(8,  a_d)
+		BN_CASE_32_BIT(7,  a_d)
+			break;
+		default: /* a->top == field->top */
+			return BN_usub(r, a, field);
+		}
+
+	BN_224_SET(t_d,10,9,8,7,0,0,0)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
+		++carry;
+	BN_224_SET(t_d,0,13,12,11,0,0,0)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
+		++carry;
+	BN_224_SET(t_d,13,12,11,10,9,8,7)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
+		--carry;
+	BN_224_SET(t_d,0,0,0,0,13,12,11)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
+		--carry;
+
+	if (carry > 0)
+		while (carry)
+			{
+			if (bn_sub_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
+				--carry;
+			}
+	else if (carry < 0)
+		while (carry)
+			{
+			if (bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
+				++carry;
+			}
+
+	r->top = BN_NIST_224_TOP;
+#if 0
+	bn_clear_top2max(r);
+#endif
+	bn_fix_top(r);
+
+	if (BN_ucmp(r, field) >= 0)
+		{
+		bn_sub_words(r_d, r_d, _nist_p_224, BN_NIST_224_TOP);
+		bn_fix_top(r);
+		}
+	return 1;
+#else
+	return 0;
+#endif
+	}
+
+static void _init_256_data(void)
+	{
+	int	i;
+	BN_ULONG *tmp1 = _256_data;
+	const BN_ULONG *tmp2 = tmp1;
+
+	memcpy(tmp1, _nist_p_256, BN_NIST_256_TOP * sizeof(BN_ULONG));
+	tmp1 += BN_NIST_256_TOP;
+
+	for (i=0; i<5; i++)
+		{
+		bn_add_words(tmp1, _nist_p_256, tmp2, BN_NIST_256_TOP);
+		tmp2  = tmp1;
+		tmp1 += BN_NIST_256_TOP;
+		}
+	_is_set_256_data = 1;
+	}
+
+#define BN_256_SET(d,a1,a2,a3,a4,a5,a6,a7,a8) \
+	{\
+	register BN_ULONG *td = (d);\
+	BN_CP_32_FROM_BUF(td,a8); BN_CP_32_FROM_BUF(td,a7);\
+	BN_CP_32_FROM_BUF(td,a6); BN_CP_32_FROM_BUF(td,a5);\
+	BN_CP_32_FROM_BUF(td,a4); BN_CP_32_FROM_BUF(td,a3);\
+	BN_CP_32_FROM_BUF(td,a2); BN_CP_32_FROM_BUF(td,a1);\
+	}
+
+int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
+	BN_CTX *ctx)
+	{
+#ifndef NO_32_BIT_TYPE
+	int	tmp_int;
+	int	carry = 0;
+	register BN_ULONG *a_d, *r_d;
+	BN_ULONG t_d[BN_NIST_256_TOP];
+	BN_ULONG t_d2[BN_NIST_256_TOP];
+	BN_32_BIT_BUF(8)  BN_32_BIT_BUF(9)
+	BN_32_BIT_BUF(10) BN_32_BIT_BUF(11)
+	BN_32_BIT_BUF(12) BN_32_BIT_BUF(13)
+	BN_32_BIT_BUF(14) BN_32_BIT_BUF(15)
+
+	if (!_is_set_256_data)
+		_init_256_data();
+
+	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);
+
+	if (r != a)
+		if (!BN_ncopy(r, a, BN_NIST_256_TOP))
+			return 0;
+
+	tmp_int = a->top-1;
+
+	a_d = a->d;
+	r_d = r->d;
+	switch (tmp_int)
+		{
+		BN_CASE_32_BIT(15, a_d)
+		BN_CASE_32_BIT(14, a_d)
+		BN_CASE_32_BIT(13, a_d)
+		BN_CASE_32_BIT(12, a_d)
+		BN_CASE_32_BIT(11, a_d)
+		BN_CASE_32_BIT(10, a_d)
+		BN_CASE_32_BIT(9,  a_d)
+		BN_CASE_32_BIT(8,  a_d)
+			break;
+		default: /* a->top == field->top */
+			return BN_usub(r, a, field);
+		}
+
+	/*S1*/
+	BN_256_SET(t_d,15,14,13,12,11,0,0,0)
+	/*S2*/
+	BN_256_SET(t_d2,0,15,14,13,12,0,0,0)
+	if (bn_add_words(t_d, t_d, t_d2, BN_NIST_256_TOP))
+		carry = 2;
+	/* left shift */
+		{
+		register BN_ULONG *ap,t,c;
+		ap = t_d;
+		c=0;
+		for (tmp_int=BN_NIST_256_TOP; tmp_int != 0; --tmp_int)
+			{
+			t= *ap;
+			*(ap++)=((t<<1)|c)&BN_MASK2;
+			c=(t & BN_TBIT)?1:0;
+			}
+		if (c)
+			++carry;
+		}
+
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		++carry;
+	/*S3*/
+	BN_256_SET(t_d,15,14,0,0,0,10,9,8)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		++carry;
+	/*S4*/
+	BN_256_SET(t_d,8,13,15,14,13,11,10,9)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		++carry;
+	/*D1*/
+	BN_256_SET(t_d,10,8,0,0,0,13,12,11)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		--carry;
+	/*D2*/
+	BN_256_SET(t_d,11,9,0,0,15,14,13,12)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		--carry;
+	/*D3*/
+	BN_256_SET(t_d,12,0,10,9,8,15,14,13)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		--carry;
+	/*D4*/
+	BN_256_SET(t_d,13,0,11,10,9,0,15,14)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+		--carry;
+	
+	if (carry)
+		{
+		if (carry > 0)
+			bn_sub_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
+				--carry, BN_NIST_256_TOP);
+		else
+			{
+			carry = -carry;
+			bn_add_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
+				--carry, BN_NIST_256_TOP);
+			}
+		}
+
+	r->top = BN_NIST_256_TOP;
+#if 0
+	bn_clear_top2max(r);
+#endif
+	bn_fix_top(r);
+
+	if (BN_ucmp(r, field) >= 0)
+		{
+		bn_sub_words(r_d, r_d, _nist_p_256, BN_NIST_256_TOP);
+		bn_fix_top(r);
+		}
+	return 1;
+#else
+	return 0;
+#endif
+	}
+
+static void _init_384_data(void)
+	{
+	int	i;
+	BN_ULONG *tmp1 = _384_data;
+	const BN_ULONG *tmp2 = tmp1;
+
+	memcpy(tmp1, _nist_p_384, BN_NIST_384_TOP * sizeof(BN_ULONG));
+	tmp1 += BN_NIST_384_TOP;
+
+	for (i=0; i<7; i++)
+		{
+		bn_add_words(tmp1, _nist_p_384, tmp2, BN_NIST_384_TOP);
+		tmp2  = tmp1;
+		tmp1 += BN_NIST_384_TOP;
+		}
+	_is_set_384_data = 1;
+	}
+
+#define BN_384_SET(d,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
+	{\
+	register BN_ULONG *td = (d);\
+	BN_CP_32_FROM_BUF(td,a12); BN_CP_32_FROM_BUF(td,a11);\
+	BN_CP_32_FROM_BUF(td,a10); BN_CP_32_FROM_BUF(td,a9);\
+	BN_CP_32_FROM_BUF(td,a8);  BN_CP_32_FROM_BUF(td,a7);\
+	BN_CP_32_FROM_BUF(td,a6);  BN_CP_32_FROM_BUF(td,a5);\
+	BN_CP_32_FROM_BUF(td,a4);  BN_CP_32_FROM_BUF(td,a3);\
+	BN_CP_32_FROM_BUF(td,a2);  BN_CP_32_FROM_BUF(td,a1);\
+	}
+
+int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
+	BN_CTX *ctx)
+	{
+#ifndef NO_32_BIT_TYPE
+	int	tmp_int;
+	int	carry = 0;
+	register BN_ULONG *r_d, *a_d;
+	BN_ULONG t_d[BN_NIST_384_TOP];
+	BN_32_BIT_BUF(12) BN_32_BIT_BUF(13)
+	BN_32_BIT_BUF(14) BN_32_BIT_BUF(15)
+	BN_32_BIT_BUF(16) BN_32_BIT_BUF(17)
+	BN_32_BIT_BUF(18) BN_32_BIT_BUF(19)
+	BN_32_BIT_BUF(20) BN_32_BIT_BUF(21)
+	BN_32_BIT_BUF(22) BN_32_BIT_BUF(23)
+
+	if (!_is_set_384_data)
+		_init_384_data();
+
+	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);
+
+	if (r != a)
+		if (!BN_ncopy(r, a, BN_NIST_384_TOP))
+			return 0;
+
+	r_d = r->d;
+	a_d = a->d;
+	tmp_int = a->top-1;
+
+	switch (tmp_int)
+		{
+		BN_CASE_32_BIT(23, a_d)
+		BN_CASE_32_BIT(22, a_d)
+		BN_CASE_32_BIT(21, a_d)
+		BN_CASE_32_BIT(20, a_d)
+		BN_CASE_32_BIT(19, a_d)
+		BN_CASE_32_BIT(18, a_d)
+		BN_CASE_32_BIT(17, a_d)
+		BN_CASE_32_BIT(16, a_d)
+		BN_CASE_32_BIT(15, a_d)
+		BN_CASE_32_BIT(14, a_d)
+		BN_CASE_32_BIT(13, a_d)
+		BN_CASE_32_BIT(12, a_d)
+			break;
+		default: /* a->top == field->top */
+			return BN_usub(r, a, field);
+		}
+
+	/*S1*/
+	BN_256_SET(t_d,0,0,0,0,0,23,22,21)
+		/* left shift */
+		{
+		register BN_ULONG *ap,t,c;
+		ap = t_d;
+		c=0;
+		for (tmp_int=BN_NIST_256_TOP; tmp_int != 0; --tmp_int)
+			{
+			t= *ap;
+			*(ap++)=((t<<1)|c)&BN_MASK2;
+			c=(t & BN_TBIT)?1:0;
+			}
+		}
+	if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
+		t_d, BN_NIST_256_TOP))
+		++carry;
+	/*S2*/
+	BN_384_SET(t_d,23,22,21,20,19,18,17,16,15,14,13,12)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		++carry;
+	/*S3*/
+	BN_384_SET(t_d,20,19,18,17,16,15,14,13,12,23,22,21)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		++carry;
+	/*S4*/
+	BN_384_SET(t_d,19,18,17,16,15,14,13,12,20,0,23,0)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		++carry;
+	/*S5*/
+	BN_256_SET(t_d,0,0,0,0,23,22,21,20)
+	if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
+		t_d, BN_NIST_256_TOP))
+		++carry;
+	/*S6*/
+	BN_384_SET(t_d,0,0,0,0,0,0,23,22,21,0,0,20)
+	if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		++carry;
+	/*D1*/
+	BN_384_SET(t_d,22,21,20,19,18,17,16,15,14,13,12,23)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		--carry;
+	/*D2*/
+	BN_384_SET(t_d,0,0,0,0,0,0,0,23,22,21,20,0)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		--carry;
+	/*D3*/
+	BN_384_SET(t_d,0,0,0,0,0,0,0,23,23,0,0,0)
+	if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+		--carry;
+	
+	if (carry)
+		{
+		if (carry > 0)
+			bn_sub_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
+				--carry, BN_NIST_384_TOP);
+		else
+			{
+			carry = -carry;
+			bn_add_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
+				--carry, BN_NIST_384_TOP);
+			}
+		}
+
+	r->top = BN_NIST_384_TOP;
+#if 0
+	bn_clear_top2max(r);
+#endif
+	bn_fix_top(r);
+
+	if (BN_ucmp(r, field) >= 0)
+		{
+		bn_sub_words(r_d, r_d, _nist_p_384, BN_NIST_384_TOP);
+		bn_fix_top(r);
+		}
+	return 1;
+#else
+	return 0;
+#endif
+	}
+
+int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
+	BN_CTX *ctx)
+	{
+#if BN_BITS2 == 64
+#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
+#elif BN_BITS2 == 32
+#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
+#elif BN_BITS2 == 16
+#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
+#elif BN_BITS2 == 8
+#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1
+#endif
+	int	top, ret = 0;
+	BN_ULONG *r_d;
+	BIGNUM	*tmp;
+
+	/* check whether a reduction is necessary */
+	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);
+
+	BN_CTX_start(ctx);
+	tmp = BN_CTX_get(ctx);
+	if (!tmp)
+		goto err;
+
+	if (!BN_ncopy(tmp, a, BN_NIST_521_TOP))
+		return 0;
+	if (!BN_rshift(r, a, 521))
+		return 0;
+
+	if (tmp->top == BN_NIST_521_TOP)
+		tmp->d[BN_NIST_521_TOP-1]  &= BN_NIST_521_TOP_MASK;
+
+	if (!BN_uadd(r, tmp, r))
+		return 0;
+	top = r->top;
+	r_d = r->d;
+	if (top == BN_NIST_521_TOP  && 
+           (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))
+		{
+		BN_NIST_ADD_ONE(r_d)
+		r_d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
+		}
+	bn_fix_top(r);
+
+	ret = 1;
+err:
+	BN_CTX_end(ctx);
+	
+	return ret;
+	}
diff --git a/crypto/ec/Makefile.ssl b/crypto/ec/Makefile.ssl
index f8d0696..16997c6 100644
--- a/crypto/ec/Makefile.ssl
+++ b/crypto/ec/Makefile.ssl
@@ -129,6 +129,7 @@
 ec_cvt.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
 ec_cvt.o: ../../include/openssl/bn.h ../../include/openssl/crypto.h
 ec_cvt.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+ec_cvt.o: ../../include/openssl/err.h ../../include/openssl/lhash.h
 ec_cvt.o: ../../include/openssl/obj_mac.h ../../include/openssl/opensslconf.h
 ec_cvt.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
 ec_cvt.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
@@ -183,6 +184,7 @@
 ecp_nist.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
 ecp_nist.o: ../../include/openssl/bn.h ../../include/openssl/crypto.h
 ecp_nist.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+ecp_nist.o: ../../include/openssl/err.h ../../include/openssl/lhash.h
 ecp_nist.o: ../../include/openssl/obj_mac.h ../../include/openssl/opensslconf.h
 ecp_nist.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
 ecp_nist.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h
index 094e05e..5abef25 100644
--- a/crypto/ec/ec.h
+++ b/crypto/ec/ec.h
@@ -127,9 +127,9 @@
  */
 const EC_METHOD *EC_GFp_simple_method(void);
 const EC_METHOD *EC_GFp_mont_method(void);
+const EC_METHOD *EC_GFp_nist_method(void);
 #if 0
 const EC_METHOD *EC_GFp_recp_method(void); /* TODO */
-const EC_METHOD *EC_GFp_nist_method(void); /* TODO */
 #endif
 
 /* EC_METHOD for curves over GF(2^m).
@@ -370,6 +370,10 @@
 #define EC_F_ECPKPARAMETERS_PRINT_FP			 150
 #define EC_F_ECPUBLICKEY_GET_OCTET			 151
 #define EC_F_ECPUBLICKEY_SET_OCTET			 152
+#define EC_F_ECP_NIST_MOD_192				 203
+#define EC_F_ECP_NIST_MOD_224				 204
+#define EC_F_ECP_NIST_MOD_256				 205
+#define EC_F_ECP_NIST_MOD_521				 206
 #define EC_F_EC_ASN1_GROUP2CURVE			 153
 #define EC_F_EC_ASN1_GROUP2FIELDID			 154
 #define EC_F_EC_ASN1_GROUP2PARAMETERS			 155
@@ -387,6 +391,9 @@
 #define EC_F_EC_GFP_MONT_FIELD_ENCODE			 134
 #define EC_F_EC_GFP_MONT_FIELD_MUL			 131
 #define EC_F_EC_GFP_MONT_FIELD_SQR			 132
+#define EC_F_EC_GFP_NIST_FIELD_MUL			 200
+#define EC_F_EC_GFP_NIST_FIELD_SQR			 201
+#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP		 202
 #define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT	 165
 #define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE		 166
 #define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP		 100
@@ -468,6 +475,7 @@
 #define EC_R_GROUP2PKPARAMETERS_FAILURE			 120
 #define EC_R_I2D_ECPKPARAMETERS_FAILURE			 121
 #define EC_R_INCOMPATIBLE_OBJECTS			 101
+#define EC_R_INTERNAL_ERROR				 132
 #define EC_R_INVALID_ARGUMENT				 112
 #define EC_R_INVALID_COMPRESSED_POINT			 110
 #define EC_R_INVALID_COMPRESSION_BIT			 109
@@ -480,10 +488,13 @@
 #define EC_R_MISSING_PRIVATE_KEY			 125
 #define EC_R_NOT_IMPLEMENTED				 126
 #define EC_R_NOT_INITIALIZED				 111
+#define EC_R_NO_FIELD_MOD				 133
 #define EC_R_NO_SUCH_EXTRA_DATA				 105
+#define EC_R_PASSED_NULL_PARAMETER			 134
 #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 22789a5..2078256 100644
--- a/crypto/ec/ec_cvt.c
+++ b/crypto/ec/ec_cvt.c
@@ -82,6 +82,7 @@
  *
  */
 
+#include <openssl/err.h>
 #include "ec_lcl.h"
 
 
@@ -89,11 +90,8 @@
 	{
 	const EC_METHOD *meth;
 	EC_GROUP *ret;
-	
-	/* Finally, this will use EC_GFp_nist_method if 'p' is a special
-	 * prime with optimized modular arithmetics (for NIST curves)
-	 */
-	meth = EC_GFp_mont_method();
+
+	meth = EC_GFp_nist_method();
 	
 	ret = EC_GROUP_new(meth);
 	if (ret == NULL)
@@ -101,8 +99,21 @@
 
 	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 */
 		EC_GROUP_clear_free(ret);
-		return NULL;
+		meth = EC_GFp_mont_method();
+
+		ret = EC_GROUP_new(meth);
+		if (ret == NULL)
+			return NULL;
+
+		if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
+			{
+			EC_GROUP_clear_free(ret);
+			return NULL;
+			}
 		}
 
 	return ret;
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 8ae2c00..71b1dcf 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -76,6 +76,10 @@
 {ERR_PACK(0,EC_F_ECPKPARAMETERS_PRINT_FP,0),	"ECPKParameters_print_fp"},
 {ERR_PACK(0,EC_F_ECPUBLICKEY_GET_OCTET,0),	"ECPUBLICKEY_GET_OCTET"},
 {ERR_PACK(0,EC_F_ECPUBLICKEY_SET_OCTET,0),	"ECPUBLICKEY_SET_OCTET"},
+{ERR_PACK(0,EC_F_ECP_NIST_MOD_192,0),	"ECP_NIST_MOD_192"},
+{ERR_PACK(0,EC_F_ECP_NIST_MOD_224,0),	"ECP_NIST_MOD_224"},
+{ERR_PACK(0,EC_F_ECP_NIST_MOD_256,0),	"ECP_NIST_MOD_256"},
+{ERR_PACK(0,EC_F_ECP_NIST_MOD_521,0),	"ECP_NIST_MOD_521"},
 {ERR_PACK(0,EC_F_EC_ASN1_GROUP2CURVE,0),	"EC_ASN1_GROUP2CURVE"},
 {ERR_PACK(0,EC_F_EC_ASN1_GROUP2FIELDID,0),	"EC_ASN1_GROUP2FIELDID"},
 {ERR_PACK(0,EC_F_EC_ASN1_GROUP2PARAMETERS,0),	"EC_ASN1_GROUP2PARAMETERS"},
@@ -93,6 +97,9 @@
 {ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_ENCODE,0),	"ec_GFp_mont_field_encode"},
 {ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_MUL,0),	"ec_GFp_mont_field_mul"},
 {ERR_PACK(0,EC_F_EC_GFP_MONT_FIELD_SQR,0),	"ec_GFp_mont_field_sqr"},
+{ERR_PACK(0,EC_F_EC_GFP_NIST_FIELD_MUL,0),	"ec_GFp_nist_field_mul"},
+{ERR_PACK(0,EC_F_EC_GFP_NIST_FIELD_SQR,0),	"ec_GFp_nist_field_sqr"},
+{ERR_PACK(0,EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP,0),	"EC_GFP_NIST_GROUP_SET_CURVE_GFP"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,0),	"ec_GFp_simple_group_check_discriminant"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE,0),	"ec_GFp_simple_group_set_curve"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP,0),	"EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
@@ -177,6 +184,7 @@
 {EC_R_GROUP2PKPARAMETERS_FAILURE         ,"group2pkparameters failure"},
 {EC_R_I2D_ECPKPARAMETERS_FAILURE         ,"i2d ecpkparameters failure"},
 {EC_R_INCOMPATIBLE_OBJECTS               ,"incompatible objects"},
+{EC_R_INTERNAL_ERROR                     ,"internal error"},
 {EC_R_INVALID_ARGUMENT                   ,"invalid argument"},
 {EC_R_INVALID_COMPRESSED_POINT           ,"invalid compressed point"},
 {EC_R_INVALID_COMPRESSION_BIT            ,"invalid compression bit"},
@@ -189,10 +197,13 @@
 {EC_R_MISSING_PRIVATE_KEY                ,"missing private key"},
 {EC_R_NOT_IMPLEMENTED                    ,"not implemented"},
 {EC_R_NOT_INITIALIZED                    ,"not initialized"},
+{EC_R_NO_FIELD_MOD                       ,"no field mod"},
 {EC_R_NO_SUCH_EXTRA_DATA                 ,"no such extra data"},
+{EC_R_PASSED_NULL_PARAMETER              ,"passed null parameter"},
 {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/ecp_nist.c b/crypto/ec/ecp_nist.c
index b1c4024..3c2b4fa 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -1,6 +1,9 @@
 /* crypto/ec/ecp_nist.c */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
 /* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -58,12 +61,14 @@
  * and contributed to the OpenSSL project.
  */
 
+#include <openssl/err.h>
+#include <openssl/obj_mac.h>
 #include "ec_lcl.h"
 
-#if 0
 const EC_METHOD *EC_GFp_nist_method(void)
 	{
 	static const EC_METHOD ret = {
+		NID_X9_62_prime_field,
 		ec_GFp_nist_group_init,
 		ec_GFp_nist_group_finish,
 		ec_GFp_nist_group_clear_finish,
@@ -71,10 +76,6 @@
 		ec_GFp_nist_group_set_curve,
 		ec_GFp_simple_group_get_curve,
 		ec_GFp_simple_group_get_degree,
-		ec_GFp_simple_group_set_generator,
-		ec_GFp_simple_group_get0_generator,
-		ec_GFp_simple_group_get_order,
-		ec_GFp_simple_group_get_cofactor,
 		ec_GFp_simple_group_check_discriminant,
 		ec_GFp_simple_point_init,
 		ec_GFp_simple_point_finish,
@@ -107,8 +108,13 @@
 
 	return &ret;
 	}
-#endif
 
+#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
 
 int ec_GFp_nist_group_init(EC_GROUP *group)
 	{
@@ -119,26 +125,154 @@
 	return ok;
 	}
 
-
-int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-/* TODO */
+void ec_GFp_nist_group_finish(EC_GROUP *group)
+	{
+	BN_free(&group->field);
+	BN_free(&group->a);
+	BN_free(&group->b);
+	}
 
 
-void ec_GFp_nist_group_finish(EC_GROUP *group);
-/* TODO */
+void ec_GFp_nist_group_clear_finish(EC_GROUP *group)
+	{
+	BN_clear_free(&group->field);
+	BN_clear_free(&group->a);
+	BN_clear_free(&group->b);
+	}
 
 
-void ec_GFp_nist_group_clear_finish(EC_GROUP *group);
-/* TODO */
+int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+	const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp_bn;
+	
+	if (ctx == NULL)
+		if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
 
+	BN_CTX_start(ctx);
+	if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err;
 
-int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
-/* TODO */
+	if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
+		group->field_data1 = (void *)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;
+#else
+		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;
+#else
+		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;
+#else
+		goto err;
+#endif
+	else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
+		group->field_data1 = (void *)BN_nist_mod_521;
+	else
+		{
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, 
+			EC_R_PRIME_IS_NOT_A_NIST_PRIME);
+		goto err;
+		}
 
+	/* group->field */
+	if (!BN_copy(&group->field, p)) goto err;
+	group->field.neg = 0;
 
-int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-/* TODO */
+	/* group->a */
+	(ECP_MOD_CAST group->field_data1)(&group->a, a, p, ctx);
 
+	/* group->b */
+	(ECP_MOD_CAST group->field_data1)(&group->b, b, p, ctx);
 
-int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
-/* TODO */
+	/* group->a_is_minus3 */
+	if (!BN_add_word(tmp_bn, 3)) goto err;
+	group->a_is_minus3 = (0 == BN_cmp(tmp_bn, &group->field));
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	if (dest == NULL || src == NULL)
+		return 0;
+
+	if (!BN_copy(&dest->field, &src->field))
+		return 0;
+	if (!BN_copy(&dest->a, &src->a))
+		return 0;
+	if (!BN_copy(&dest->b, &src->b))
+		return 0;
+
+	dest->curve_name  = src->curve_name;
+
+	dest->a_is_minus3 = src->a_is_minus3;
+
+	dest->field_data1 = src->field_data1;
+
+	return 1;
+	}
+
+int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+	const BIGNUM *b, BN_CTX *ctx)
+	{
+	int	ret=0;
+	BN_CTX	*ctx_new=NULL;
+
+	if (!group || !r || !a || !b)
+		{
+		ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+		}
+	if (!ctx)
+		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))
+		goto err;
+
+	ret=1;
+err:
+	if (ctx_new)
+		BN_CTX_free(ctx_new);
+	return ret;
+	}
+
+int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+	BN_CTX *ctx)
+	{
+	int	ret=0;
+	BN_CTX	*ctx_new=NULL;
+
+	if (!group || !r || !a)
+		{
+		ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
+		goto err;
+		}
+	if (!ctx)
+		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))
+		goto err;
+
+	ret=1;
+err:
+	if (ctx_new)
+		BN_CTX_free(ctx_new);
+	return ret;
+	}
diff --git a/util/libeay.num b/util/libeay.num
index 3c7b1e8..9c7a1ee 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -3022,3 +3022,15 @@
 i2d_PKCS7_NDEF                          3455	EXIST::FUNCTION:
 ENGINE_up_ref                           3456	EXIST::FUNCTION:
 ENGINE_get_static_state                 3457	EXIST::FUNCTION:
+BN_get0_nist_prime_384                  3458	EXIST::FUNCTION:
+BN_ncopy                                3459	EXIST::FUNCTION:
+BN_nist_mod_224                         3460	EXIST::FUNCTION:
+BN_nist_mod_256                         3461	EXIST::FUNCTION:
+EC_GFp_nist_method                      3462	EXIST::FUNCTION:EC
+BN_nist_mod_384                         3463	EXIST::FUNCTION:
+BN_get0_nist_prime_192                  3464	EXIST::FUNCTION:
+BN_get0_nist_prime_521                  3465	EXIST::FUNCTION:
+BN_get0_nist_prime_224                  3466	EXIST::FUNCTION:
+BN_get0_nist_prime_256                  3467	EXIST::FUNCTION:
+BN_nist_mod_192                         3468	EXIST::FUNCTION:
+BN_nist_mod_521                         3469	EXIST::FUNCTION: