add X9.31 prime generation routines from 0.9.8 branch
authorDr. Stephen Henson <steve@openssl.org>
Sun, 9 Jan 2011 13:22:47 +0000 (13:22 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 9 Jan 2011 13:22:47 +0000 (13:22 +0000)
crypto/bn/Makefile
crypto/bn/bn.h
crypto/bn/bn_x931p.c [new file with mode: 0644]

index aabc4f56b8e6dd057ff821e09e4f66ea9692a0b2..1ef583726c6f42c91f615256703120c25f7fba2d 100644 (file)
@@ -26,13 +26,13 @@ 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_nist.c \
-       bn_depr.c bn_const.c
+       bn_depr.c bn_const.c bn_x931p.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_nist.o \
-       bn_depr.o bn_const.o
+       bn_depr.o bn_const.o bn_x931p.o
 
 SRC= $(LIBSRC)
 
index e484b7fc1160191bf207445e6cd8967911c6f4ff..7fe78bb774fb963a732628b0f3fa544bb35e0e55 100644 (file)
@@ -540,6 +540,17 @@ int        BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
 int    BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
                int do_trial_division, BN_GENCB *cb);
 
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+                       const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       BIGNUM *Xp1, BIGNUM *Xp2,
+                       const BIGNUM *Xp,
+                       const BIGNUM *e, BN_CTX *ctx,
+                       BN_GENCB *cb);
+
 BN_MONT_CTX *BN_MONT_CTX_new(void );
 void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
 int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c
new file mode 100644 (file)
index 0000000..04c5c87
--- /dev/null
@@ -0,0 +1,272 @@
+/* bn_x931p.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 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
+ *    licensing@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 <stdio.h>
+#include <openssl/bn.h>
+
+/* X9.31 routines for prime derivation */
+
+/* X9.31 prime derivation. This is used to generate the primes pi
+ * (p1, p2, q1, q2) from a parameter Xpi by checking successive odd
+ * integers.
+ */
+
+static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
+                       BN_GENCB *cb)
+       {
+       int i = 0;
+       if (!BN_copy(pi, Xpi))
+               return 0;
+       if (!BN_is_odd(pi) && !BN_add_word(pi, 1))
+               return 0;
+       for(;;)
+               {
+               i++;
+               BN_GENCB_call(cb, 0, i);
+               /* NB 27 MR is specificed in X9.31 */
+               if (BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb))
+                       break;
+               if (!BN_add_word(pi, 2))
+                       return 0;
+               }
+       BN_GENCB_call(cb, 2, i);
+       return 1;
+       }
+
+/* This is the main X9.31 prime derivation function. From parameters
+ * Xp1, Xp2 and Xp derive the prime p. If the parameters p1 or p2 are
+ * not NULL they will be returned too: this is needed for testing.
+ */
+
+int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+                       const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)
+       {
+       int ret = 0;
+
+       BIGNUM *t, *p1p2, *pm1;
+
+       /* Only even e supported */
+       if (!BN_is_odd(e))
+               return 0;
+
+       BN_CTX_start(ctx);
+       if (!p1)
+               p1 = BN_CTX_get(ctx);
+
+       if (!p2)
+               p2 = BN_CTX_get(ctx);
+
+       t = BN_CTX_get(ctx);
+
+       p1p2 = BN_CTX_get(ctx);
+
+       pm1 = BN_CTX_get(ctx);
+
+       if (!bn_x931_derive_pi(p1, Xp1, ctx, cb))
+               goto err;
+
+       if (!bn_x931_derive_pi(p2, Xp2, ctx, cb))
+               goto err;
+
+       if (!BN_mul(p1p2, p1, p2, ctx))
+               goto err;
+
+       /* First set p to value of Rp */
+
+       if (!BN_mod_inverse(p, p2, p1, ctx))
+               goto err;
+
+       if (!BN_mul(p, p, p2, ctx))
+               goto err;
+
+       if (!BN_mod_inverse(t, p1, p2, ctx))
+               goto err;
+
+       if (!BN_mul(t, t, p1, ctx))
+               goto err;
+
+       if (!BN_sub(p, p, t))
+               goto err;
+
+       if (p->neg && !BN_add(p, p, p1p2))
+               goto err;
+
+       /* p now equals Rp */
+
+       if (!BN_mod_sub(p, p, Xp, p1p2, ctx))
+               goto err;
+
+       if (!BN_add(p, p, Xp))
+               goto err;
+
+       /* p now equals Yp0 */
+
+       for (;;)
+               {
+               int i = 1;
+               BN_GENCB_call(cb, 0, i++);
+               if (!BN_copy(pm1, p))
+                       goto err;
+               if (!BN_sub_word(pm1, 1))
+                       goto err;
+               if (!BN_gcd(t, pm1, e, ctx))
+                       goto err;
+               if (BN_is_one(t)
+               /* X9.31 specifies 8 MR and 1 Lucas test or any prime test
+                * offering similar or better guarantees 50 MR is considerably 
+                * better.
+                */
+                       && BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb))
+                       break;
+               if (!BN_add(p, p, p1p2))
+                       goto err;
+               }
+
+       BN_GENCB_call(cb, 3, 0);
+
+       ret = 1;
+
+       err:
+
+       BN_CTX_end(ctx);
+
+       return ret;
+       }
+
+/* Generate pair of paramters Xp, Xq for X9.31 prime generation.
+ * Note: nbits paramter is sum of number of bits in both.
+ */
+
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
+       {
+       BIGNUM *t;
+       int i;
+       /* Number of bits for each prime is of the form
+        * 512+128s for s = 0, 1, ...
+        */
+       if ((nbits < 1024) || (nbits & 0xff))
+               return 0;
+       nbits >>= 1;
+       /* The random value Xp must be between sqrt(2) * 2^(nbits-1) and
+        * 2^nbits - 1. By setting the top two bits we ensure that the lower
+        * bound is exceeded.
+        */
+       if (!BN_rand(Xp, nbits, 1, 0))
+               return 0;
+
+       BN_CTX_start(ctx);
+       t = BN_CTX_get(ctx);
+
+       for (i = 0; i < 1000; i++)
+               {
+               if (!BN_rand(Xq, nbits, 1, 0))
+                       return 0;
+               /* Check that |Xp - Xq| > 2^(nbits - 100) */
+               BN_sub(t, Xp, Xq);
+               if (BN_num_bits(t) > (nbits - 100))
+                       break;
+               }
+
+       BN_CTX_end(ctx);
+
+       if (i < 1000)
+               return 1;
+
+       return 0;
+
+       }
+
+/* Generate primes using X9.31 algorithm. Of the values p, p1, p2, Xp1
+ * and Xp2 only 'p' needs to be non-NULL. If any of the others are not NULL
+ * the relevant parameter will be stored in it.
+ *
+ * Due to the fact that |Xp - Xq| > 2^(nbits - 100) must be satisfied Xp and Xq
+ * are generated using the previous function and supplied as input.
+ */
+
+int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       BIGNUM *Xp1, BIGNUM *Xp2,
+                       const BIGNUM *Xp,
+                       const BIGNUM *e, BN_CTX *ctx,
+                       BN_GENCB *cb)
+       {
+       int ret = 0;
+
+       BN_CTX_start(ctx);
+       if (!Xp1)
+               Xp1 = BN_CTX_get(ctx);
+       if (!Xp2)
+               Xp2 = BN_CTX_get(ctx);
+
+       if (!BN_rand(Xp1, 101, 0, 0))
+               goto error;
+       if (!BN_rand(Xp2, 101, 0, 0))
+               goto error;
+       if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb))
+               goto error;
+
+       ret = 1;
+
+       error:
+       BN_CTX_end(ctx);
+
+       return ret;
+
+       }
+