fast reduction for NIST curves
authorBodo Möller <bodo@openssl.org>
Mon, 28 Oct 2002 13:23:24 +0000 (13:23 +0000)
committerBodo Möller <bodo@openssl.org>
Mon, 28 Oct 2002 13:23:24 +0000 (13:23 +0000)
Submitted by: Nils Larsch

12 files changed:
CHANGES
apps/speed.c
crypto/bn/Makefile.ssl
crypto/bn/bn.h
crypto/bn/bn_lib.c
crypto/bn/bn_nist.c [new file with mode: 0644]
crypto/ec/Makefile.ssl
crypto/ec/ec.h
crypto/ec/ec_cvt.c
crypto/ec/ec_err.c
crypto/ec/ecp_nist.c
util/libeay.num

diff --git a/CHANGES b/CHANGES
index c211f4b..c22b945 100644 (file)
--- 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
index a8a375f..ac643bd 100644 (file)
@@ -261,7 +261,7 @@ static int do_multi(int multi);
 #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 @@ int MAIN(int argc, char **argv)
 #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 @@ int MAIN(int argc, char **argv)
        {       
        /* Prime Curves */
        NID_secp160r1,
+       NID_X9_62_prime192v1,
        NID_secp224r1,
        NID_X9_62_prime256v1,
        NID_secp384r1,
@@ -580,6 +582,7 @@ int MAIN(int argc, char **argv)
        {
        /* Prime Curves */
        "secp160r1",
+       "nistp192",
        "nistp224",
        "nistp256",
        "nistp384",
@@ -598,7 +601,7 @@ int MAIN(int argc, char **argv)
        };
        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
         };
index e54f066..54a3ead 100644 (file)
@@ -39,12 +39,12 @@ LIB=$(TOP)/libcrypto.a
 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/lhash.h ../../include/openssl/opensslconf.h
 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
index 1170465..21a1a90 100644 (file)
@@ -355,6 +355,8 @@ BIGNUM *BN_new(void);
 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_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a, const unsigned int p[
 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 @@ BIGNUM *bn_dup_expand(const BIGNUM *a, int words);
                } \
        }
 
+#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);
index 20f851c..fc610e0 100644 (file)
@@ -522,6 +522,51 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
        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 (file)
index 0000000..4e21a05
--- /dev/null
@@ -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;
+       }
index f8d0696..16997c6 100644 (file)
@@ -129,6 +129,7 @@ ec_curve.o: ../../include/openssl/symhacks.h ec_curve.c ec_lcl.h
 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_mont.o: ../../include/openssl/symhacks.h ec_lcl.h ecp_mont.c
 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
index 094e05e..5abef25 100644 (file)
@@ -127,9 +127,9 @@ typedef struct ec_point_st EC_POINT;
  */
 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 @@ void ERR_load_EC_strings(void);
 #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 @@ void ERR_load_EC_strings(void);
 #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 @@ void ERR_load_EC_strings(void);
 #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 @@ void ERR_load_EC_strings(void);
 #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
index 22789a5..2078256 100644 (file)
@@ -82,6 +82,7 @@
  *
  */
 
+#include <openssl/err.h>
 #include "ec_lcl.h"
 
 
@@ -89,11 +90,8 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
        {
        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 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
 
        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;
index 8ae2c00..71b1dcf 100644 (file)
@@ -76,6 +76,10 @@ static ERR_STRING_DATA EC_str_functs[]=
 {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 @@ static ERR_STRING_DATA EC_str_functs[]=
 {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 @@ static ERR_STRING_DATA EC_str_reasons[]=
 {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 @@ static ERR_STRING_DATA EC_str_reasons[]=
 {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"},
index b1c4024..3c2b4fa 100644 (file)
@@ -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
  * 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 @@ const EC_METHOD *EC_GFp_nist_method(void)
                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 @@ const EC_METHOD *EC_GFp_nist_method(void)
 
        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 @@ int ec_GFp_nist_group_init(EC_GROUP *group)
        return ok;
        }
 
+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_clear_finish(EC_GROUP *group)
+       {
+       BN_clear_free(&group->field);
+       BN_clear_free(&group->a);
+       BN_clear_free(&group->b);
+       }
+
+
+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;
+
+       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;
+
+       /* 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);
+
+       /* 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;
 
-int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-/* TODO */
+       dest->curve_name  = src->curve_name;
 
+       dest->a_is_minus3 = src->a_is_minus3;
 
-void ec_GFp_nist_group_finish(EC_GROUP *group);
-/* TODO */
+       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;
 
-void ec_GFp_nist_group_clear_finish(EC_GROUP *group);
-/* TODO */
+       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;
 
-int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
-/* TODO */
+       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;
 
-int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
-/* TODO */
+       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;
 
-int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
-/* TODO */
+       ret=1;
+err:
+       if (ctx_new)
+               BN_CTX_free(ctx_new);
+       return ret;
+       }
index 3c7b1e8..9c7a1ee 100755 (executable)
@@ -3022,3 +3022,15 @@ ASN1_item_ndef_i2d                      3454     EXIST::FUNCTION:
 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: