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 c211f4b0e0afb4ee9425b1b4f0a7f5898659ee9e..c22b94553a95eaf1a2727f438fb50ee76ed88dd5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 0.9.7 and 0.9.8  [xx XXX 2002]
 
 
  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
   *) 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 a8a375ff2d49302a7f09dbe92a745258cee09eaa..ac643bd98689ebf1aacfa04efac3af7f8f4ed8a1 100644 (file)
@@ -261,7 +261,7 @@ static int do_multi(int multi);
 #define RSA_NUM                4
 #define DSA_NUM                3
 
 #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]={
 #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_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];
 
 #ifndef OPENSSL_NO_RSA
        RSA *rsa_key[RSA_NUM];
@@ -560,6 +561,7 @@ int MAIN(int argc, char **argv)
        {       
        /* Prime Curves */
        NID_secp160r1,
        {       
        /* Prime Curves */
        NID_secp160r1,
+       NID_X9_62_prime192v1,
        NID_secp224r1,
        NID_X9_62_prime256v1,
        NID_secp384r1,
        NID_secp224r1,
        NID_X9_62_prime256v1,
        NID_secp384r1,
@@ -580,6 +582,7 @@ int MAIN(int argc, char **argv)
        {
        /* Prime Curves */
        "secp160r1",
        {
        /* Prime Curves */
        "secp160r1",
+       "nistp192",
        "nistp224",
        "nistp256",
        "nistp384",
        "nistp224",
        "nistp256",
        "nistp384",
@@ -598,7 +601,7 @@ int MAIN(int argc, char **argv)
        };
        static int test_curves_bits[EC_NUM] =
         {
        };
        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
         };
         163, 233, 283, 409, 571,
         163, 233, 283, 409, 571
         };
index e54f0665785ca9ddab497038b6eea2c16cdb9cbb..54a3ead15aa8b619269e885964af342673a505d4 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 \
 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) \
 
 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)
 
 
 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_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
 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 1170465b1f682eb1bbd67d2359f79b2c394879f1..21a1a90143a3e51949503f2ba8539ffb5a9e8fe2 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);
 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);
 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);
 
 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)?\
 /* 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);
 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 20f851cc6692e45050ef41cbc16589e70264839b..fc610e04380d7e2ced3cb965228a2a8202422520 100644 (file)
@@ -522,6 +522,51 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
        return(a);
        }
 
        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;
 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 f8d0696a34b0cd3c87ee858298c5e3ddf32cf68c..16997c6125af0cb0ad35b7ac10a4d35d86e8256e 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/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
 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/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
 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 094e05e1685f34c3decd3a717f52cfc535e640c0..5abef25f09535ef52e34ae85dfc0bae7ca088244 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_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 */
 #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).
 #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_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
 #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_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
 #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_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
 #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_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_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_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
 #define EC_R_SLOT_FULL                                  108
 #define EC_R_UNDEFINED_GENERATOR                        113
 #define EC_R_UNDEFINED_ORDER                            128
index 22789a57e5cc46439e9a7f361636614639923f51..20782569a9faddf1332869e3e624b60ab379c3c4 100644 (file)
@@ -82,6 +82,7 @@
  *
  */
 
  *
  */
 
+#include <openssl/err.h>
 #include "ec_lcl.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;
        {
        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)
        
        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))
                {
 
        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);
                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;
                }
 
        return ret;
index 8ae2c00e32205743f563d04f4fcfd1e91051843c..71b1dcff220c6ed9f2acefdb0f0fd01b0a655281 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_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"},
 {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_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"},
 {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_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"},
 {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_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_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_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"},
 {EC_R_SLOT_FULL                          ,"slot full"},
 {EC_R_UNDEFINED_GENERATOR                ,"undefined generator"},
 {EC_R_UNDEFINED_ORDER                    ,"undefined order"},
index b1c4024c2a7ec83fbc738440bf375b47f02a8319..3c2b4fa9786235001d3b78a1a80f27d15d9d568d 100644 (file)
@@ -1,6 +1,9 @@
 /* crypto/ec/ecp_nist.c */
 /* 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
  *
  * 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.
  */
 
  * and contributed to the OpenSSL project.
  */
 
+#include <openssl/err.h>
+#include <openssl/obj_mac.h>
 #include "ec_lcl.h"
 
 #include "ec_lcl.h"
 
-#if 0
 const EC_METHOD *EC_GFp_nist_method(void)
        {
        static const EC_METHOD ret = {
 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,
                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_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,
                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;
        }
 
        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)
        {
 
 int ec_GFp_nist_group_init(EC_GROUP *group)
        {
@@ -119,26 +125,154 @@ int ec_GFp_nist_group_init(EC_GROUP *group)
        return ok;
        }
 
        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 3c7b1e8b82de16344e141562ef19f434ff3824a5..9c7a1eebeb1471d69f8cb8d268fe77a005e017a0 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:
 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: