[git] GCRYPT - branch, gniibe-curve25519, created. libgcrypt-1.6.0-107-ga879203

by NIIBE Yutaka cvs at cvs.gnupg.org
Thu Jun 11 09:30:53 CEST 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, gniibe-curve25519 has been created
        at  a879203e07dc2b3e31a22be3e1649b231f49fc95 (commit)

- Log -----------------------------------------------------------------
commit a879203e07dc2b3e31a22be3e1649b231f49fc95
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jul 4 12:26:30 2014 +0900

    Add FIXME marks.

diff --git a/.gitignore b/.gitignore
index 3929e4d..87934c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+build-aux/test-driver
+test-driver
 *.lo
 *.o
 .deps/
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index e7dbc17..76dd1d8 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -1160,6 +1160,7 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
                                             &encpk, &encpklen))
             return mpi_set_opaque (NULL, encpk, encpklen*8);
         }
+      // FIXME Montgomery
     }
 
   return NULL;
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 3f284fe..12776f2 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -280,6 +280,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
       if (!Q)
         Q = mpi_point_new (0);
       if (Q)
+	// FIXME
         _gcry_mpi_ec_mul_point (Q, d, G, ec);
     }
 
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 676cc79..99b0880 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -134,8 +134,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * Currently, we distinguish the two curves by ECC_DIALECT_ED25519
    * and MPI_EC_MONTGOMERY, which works, but is not that correct.
    */
-  if (ctx->dialect == ECC_DIALECT_ED25519
-      || E->model == MPI_EC_MONTGOMERY)
+  if (ctx->dialect == ECC_DIALECT_ED25519 || E->model == MPI_EC_MONTGOMERY)
     {
       char *rndbuf;
 
@@ -152,6 +151,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
 
 
   /* Compute Q.  */
+  // FIXME
   _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx);
 
   /* Copy the stuff to the key structures. */
@@ -569,6 +569,8 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
       public = _gcry_ecc_ec2os (x, y, sk.E.p);
     }
+  // FIXME Montgomery
+
   secret = sk.d; sk.d = NULL;
   if (E.name)
     {
@@ -1261,6 +1263,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     point_init (&R);
 
     /* R = kQ  <=>  R = kdG  */
+    // FIXME
     _gcry_mpi_ec_mul_point (&R, data, &pk.Q, ec);
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
@@ -1268,6 +1271,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
 
     /* R = kG */
+    // FIXME
     _gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec);
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
@@ -1419,6 +1423,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
                                     sk.E.p, sk.E.a, sk.E.b);
 
   /* R = dkG */
+  // FIXME
   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so:  */
@@ -1733,6 +1738,8 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
     {
       mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
     }
+  // FIXME Montgomery
+
   if (!mpi_Q)
     {
       rc = GPG_ERR_BROKEN_PUBKEY;

commit 79caa02472081c9fb7f22659b84be5b21d215f1e
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jun 20 12:14:24 2014 +0900

    fix mpi_swap_conditional and update mpi_ec_mul_point.

diff --git a/mpi/ec.c b/mpi/ec.c
index 49084f9..8071994 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1181,7 +1181,9 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       unsigned int nbits;
       int j;
       mpi_point_struct p1_, p2_;
+      mpi_point_t q1, q2, prd, sum;
       unsigned long sw;
+      size_t nlimbs;
 
       /* FIXME: it's just for Curve25519 */
       mpi_clear_bit (scalar, 255);
@@ -1200,24 +1202,33 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       p2.x  = mpi_copy (point->x);
       mpi_set_ui (p2.z, 1);
 
+      nlimbs = 2*(nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB+1;
+      mpi_resize (p1.x, nlimbs);
+      mpi_resize (p1.z, nlimbs);
+      mpi_resize (p2.x, nlimbs);
+      mpi_resize (p2.z, nlimbs);
+      mpi_resize (p1_.x, nlimbs);
+      mpi_resize (p1_.z, nlimbs);
+      mpi_resize (p2_.x, nlimbs);
+      mpi_resize (p2_.z, nlimbs);
+
+      q1 = &p1;
+      q2 = &p2;
+      prd = &p1_;
+      sum = &p2_;
       for (j=nbits-1; j >= 0; j--)
         {
-	  sw = mpi_test_bit (scalar, j);
-	  mpi_swap_conditional (p1.x, p2.x, sw);
-	  mpi_swap_conditional (p1.z, p2.z, sw);
-          dup_and_add_montgomery (&p1_, &p2_, &p1, &p2, point->x, ctx);
-	  mpi_swap_conditional (p1_.x, p2_.x, sw);
-	  mpi_swap_conditional (p1_.z, p2_.z, sw);
-
-          if (--j < 0)
-            break;
-
-	  sw = mpi_test_bit (scalar, j);
-	  mpi_swap_conditional (p1_.x, p2_.x, sw);
-	  mpi_swap_conditional (p1_.z, p2_.z, sw);
-          dup_and_add_montgomery (&p1, &p2, &p1_, &p2_, point->x, ctx);
-	  mpi_swap_conditional (p1.x, p2.x, sw);
-	  mpi_swap_conditional (p1.z, p2.z, sw);
+          mpi_point_t t;
+
+          sw = mpi_test_bit (scalar, j);
+          mpi_swap_conditional (q1->x, q2->x, sw);
+          mpi_swap_conditional (q1->z, q2->z, sw);
+          dup_and_add_montgomery (prd, sum, q1, q2, point->x, ctx);
+          mpi_swap_conditional (prd->x, sum->x, sw);
+          mpi_swap_conditional (prd->z, sum->z, sw);
+
+          t = q1;  q1 = prd;  prd = t;
+          t = q2;  q2 = sum;  sum = t;
         }
 
       mpi_clear (result->y);
@@ -1226,18 +1237,18 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       mpi_swap_conditional (p1.z, p1_.z, sw);
 
       if (p1.z->nlimbs == 0)
-	{
-	  mpi_set_ui (result->x, 1);
-	  mpi_set_ui (result->z, 0);
-	}
+        {
+          mpi_set_ui (result->x, 1);
+          mpi_set_ui (result->z, 0);
+        }
       else
-	{
-	  z1 = mpi_new (0);
-	  ec_invm (z1, p1.z, ctx);
-	  ec_mulm (result->x, p1.x, z1, ctx);
-	  mpi_set_ui (result->z, 1);
-	  mpi_free (z1);
-	}
+        {
+          z1 = mpi_new (0);
+          ec_invm (z1, p1.z, ctx);
+          ec_mulm (result->x, p1.x, z1, ctx);
+          mpi_set_ui (result->z, 1);
+          mpi_free (z1);
+        }
 
       point_free (&p1);
       point_free (&p2);
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index df37542..5e77e12 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -544,35 +544,13 @@ _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
 void
 _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
 {
-#if 1
-  if (swap)
-    _gcry_mpi_swap (a, b);
-#else
   size_t i;
-  size_t nlimbs = a->nlimbs;
-  unsigned long mask = -(long)swap;
+  size_t nlimbs = a->alloced;
+  unsigned long mask = 0UL - !!swap;
   unsigned long x;
 
-  if (b->alloced < a->nlimbs)
-    {
-      mpi_resize (b, a->nlimbs);
-      nlimbs = a->nlimbs;
-    }
-  else if (a->alloced < b->nlimbs)
-    {
-      mpi_resize (a, b->nlimbs);
-      nlimbs = b->nlimbs;
-    }
-  else if (b->nlimbs < a->nlimbs)
-    {
-      mpi_resize (b, a->nlimbs);
-      nlimbs = b->nlimbs = a->nlimbs;
-    }
-  else if (a->nlimbs < b->nlimbs)
-    {
-      mpi_resize (a, b->nlimbs);
-      nlimbs = a->nlimbs = b->nlimbs;
-    }
+  if (a->alloced != b->alloced)
+    log_bug ("mpi_swap_conditional: different sizes\n");
 
   for (i = 0; i < nlimbs; i++)
     {
@@ -581,10 +559,13 @@ _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
       b->d[i] = b->d[i] ^ x;
     }
 
+  x = mask & (a->nlimbs ^ b->nlimbs);
+  a->nlimbs = a->nlimbs ^ x;
+  b->nlimbs = b->nlimbs ^ x;
+
   x = mask & (a->sign ^ b->sign);
   a->sign = a->sign ^ x;
   b->sign = b->sign ^ x;
-#endif
 }
 
 

commit bd3c93a68c0e8f4c88059736438714be4f42e45c
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jun 20 09:47:46 2014 +0900

    Don't support special x-only format by os2ec.

diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 595aa0c..3f284fe 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -202,13 +202,8 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
     }
   if (*buf != 4)
     {
-      /* x-coordinate only */
-      mpi_set (result->x, value);
-      mpi_clear (result->y);
-      mpi_set_ui (result->z, 1);
-
       xfree (buf_memory);
-      return 0;
+      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
     }
   if ( ((n-1)%2) )
     {

commit fcc2bb325a2edd1ae3b2a33add17fea5921cd050
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jun 20 09:08:37 2014 +0900

    This works.

diff --git a/cipher/ecc.c b/cipher/ecc.c
index 6a60785..676cc79 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -371,7 +371,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }
 
   /* Check order of curve.  */
-  if (sk->E.dialect != ECC_DIALECT_ED25519)
+  if (sk->E.dialect != ECC_DIALECT_ED25519 && sk->E.model != MPI_EC_MONTGOMERY)
     {
       _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
       if (mpi_cmp_ui (Q.z, 0))
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index ed14cdb..df37542 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -544,6 +544,10 @@ _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
 void
 _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
 {
+#if 1
+  if (swap)
+    _gcry_mpi_swap (a, b);
+#else
   size_t i;
   size_t nlimbs = a->nlimbs;
   unsigned long mask = -(long)swap;
@@ -580,6 +584,7 @@ _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
   x = mask & (a->sign ^ b->sign);
   a->sign = a->sign ^ x;
   b->sign = b->sign ^ x;
+#endif
 }
 
 

commit 2272df06225f0b42cc480d32b17214a1b70cd0b3
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jun 19 17:51:10 2014 +0900

    scalar handling.

diff --git a/mpi/ec.c b/mpi/ec.c
index 3476957..49084f9 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1183,6 +1183,13 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       mpi_point_struct p1_, p2_;
       unsigned long sw;
 
+      /* FIXME: it's just for Curve25519 */
+      mpi_clear_bit (scalar, 255);
+      mpi_set_bit (scalar, 254);
+      mpi_clear_bit (scalar, 2);
+      mpi_clear_bit (scalar, 1);
+      mpi_clear_bit (scalar, 0);
+
       nbits = mpi_get_nbits (scalar);
       point_init (&p1);
       point_init (&p2);
@@ -1213,7 +1220,6 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 	  mpi_swap_conditional (p1.z, p2.z, sw);
         }
 
-      z1 = mpi_new (0);
       mpi_clear (result->y);
       sw = (nbits & 1);
       mpi_swap_conditional (p1.x, p1_.x, sw);
@@ -1226,12 +1232,13 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 	}
       else
 	{
+	  z1 = mpi_new (0);
 	  ec_invm (z1, p1.z, ctx);
 	  ec_mulm (result->x, p1.x, z1, ctx);
 	  mpi_set_ui (result->z, 1);
+	  mpi_free (z1);
 	}
 
-      mpi_free (z1);
       point_free (&p1);
       point_free (&p2);
       point_free (&p1_);
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index e0afec0..ed14cdb 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -547,6 +547,7 @@ _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
   size_t i;
   size_t nlimbs = a->nlimbs;
   unsigned long mask = -(long)swap;
+  unsigned long x;
 
   if (b->alloced < a->nlimbs)
     {
@@ -571,10 +572,14 @@ _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
 
   for (i = 0; i < nlimbs; i++)
     {
-      unsigned long x = mask & (a->d[i] ^ b->d[i]);
+      x = mask & (a->d[i] ^ b->d[i]);
       a->d[i] = a->d[i] ^ x;
       b->d[i] = b->d[i] ^ x;
     }
+
+  x = mask & (a->sign ^ b->sign);
+  a->sign = a->sign ^ x;
+  b->sign = b->sign ^ x;
 }
 
 

commit 57693973f73f22e24e909fc0782e00479e12aa44
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jun 19 17:48:50 2014 +0900

    simplify

diff --git a/mpi/ec.c b/mpi/ec.c
index f2dd0f0..3476957 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1195,31 +1195,21 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 
       for (j=nbits-1; j >= 0; j--)
         {
-          mpi_point_t q1, q2;
-
 	  sw = mpi_test_bit (scalar, j);
-	  q1 = &p1;
-	  q2 = &p2;
-	  mpi_swap_conditional (q1->x, q2->x, sw);
-	  mpi_swap_conditional (q1->y, q2->y, sw);
-	  mpi_swap_conditional (q1->z, q2->z, sw);
-          dup_and_add_montgomery (&p1_, &p2_, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1.x, p2.x, sw);
+	  mpi_swap_conditional (p1.z, p2.z, sw);
+          dup_and_add_montgomery (&p1_, &p2_, &p1, &p2, point->x, ctx);
 	  mpi_swap_conditional (p1_.x, p2_.x, sw);
-	  mpi_swap_conditional (p1_.y, p2_.y, sw);
 	  mpi_swap_conditional (p1_.z, p2_.z, sw);
 
           if (--j < 0)
             break;
 
 	  sw = mpi_test_bit (scalar, j);
-	  q1 = &p1_;
-	  q2 = &p2_;
-	  mpi_swap_conditional (q1->x, q2->x, sw);
-	  mpi_swap_conditional (q1->y, q2->y, sw);
-	  mpi_swap_conditional (q1->z, q2->z, sw);
-          dup_and_add_montgomery (&p1, &p2, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1_.x, p2_.x, sw);
+	  mpi_swap_conditional (p1_.z, p2_.z, sw);
+          dup_and_add_montgomery (&p1, &p2, &p1_, &p2_, point->x, ctx);
 	  mpi_swap_conditional (p1.x, p2.x, sw);
-	  mpi_swap_conditional (p1.y, p2.y, sw);
 	  mpi_swap_conditional (p1.z, p2.z, sw);
         }
 
@@ -1227,7 +1217,6 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       mpi_clear (result->y);
       sw = (nbits & 1);
       mpi_swap_conditional (p1.x, p1_.x, sw);
-      mpi_swap_conditional (p1.y, p1_.y, sw);
       mpi_swap_conditional (p1.z, p1_.z, sw);
 
       if (p1.z->nlimbs == 0)

commit 7eba36282d648a74bbc22826e5ed2156278186cf
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jun 19 14:46:09 2014 +0900

    use mpi_swap_conditional

diff --git a/mpi/ec.c b/mpi/ec.c
index b312f53..f2dd0f0 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1181,6 +1181,7 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       unsigned int nbits;
       int j;
       mpi_point_struct p1_, p2_;
+      unsigned long sw;
 
       nbits = mpi_get_nbits (scalar);
       point_init (&p1);
@@ -1195,75 +1196,51 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       for (j=nbits-1; j >= 0; j--)
         {
           mpi_point_t q1, q2;
-          mpi_point_t sum_n, prd_n;
 
-          if (mpi_test_bit (scalar, j))
-            {
-              q1 = &p2;
-              q2 = &p1;
-              sum_n = &p1_;
-              prd_n = &p2_;
-            }
-          else
-            {
-              q1 = &p1;
-              q2 = &p2;
-              sum_n = &p2_;
-              prd_n = &p1_;
-            }
-          dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+	  sw = mpi_test_bit (scalar, j);
+	  q1 = &p1;
+	  q2 = &p2;
+	  mpi_swap_conditional (q1->x, q2->x, sw);
+	  mpi_swap_conditional (q1->y, q2->y, sw);
+	  mpi_swap_conditional (q1->z, q2->z, sw);
+          dup_and_add_montgomery (&p1_, &p2_, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1_.x, p2_.x, sw);
+	  mpi_swap_conditional (p1_.y, p2_.y, sw);
+	  mpi_swap_conditional (p1_.z, p2_.z, sw);
 
           if (--j < 0)
             break;
 
-          if (mpi_test_bit (scalar, j))
-            {
-              q1 = &p2_;
-              q2 = &p1_;
-              sum_n = &p1;
-              prd_n = &p2;
-            }
-          else
-            {
-              q1 = &p1_;
-              q2 = &p2_;
-              sum_n = &p2;
-              prd_n = &p1;
-            }
-
-          dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+	  sw = mpi_test_bit (scalar, j);
+	  q1 = &p1_;
+	  q2 = &p2_;
+	  mpi_swap_conditional (q1->x, q2->x, sw);
+	  mpi_swap_conditional (q1->y, q2->y, sw);
+	  mpi_swap_conditional (q1->z, q2->z, sw);
+          dup_and_add_montgomery (&p1, &p2, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1.x, p2.x, sw);
+	  mpi_swap_conditional (p1.y, p2.y, sw);
+	  mpi_swap_conditional (p1.z, p2.z, sw);
         }
 
       z1 = mpi_new (0);
       mpi_clear (result->y);
-      if ((nbits & 1))
-        {
-	  if (p1_.z->nlimbs == 0)
-	    {
-	      mpi_set_ui (result->x, 1);
-	      mpi_set_ui (result->z, 0);
-	    }
-	  else
-	    {
-	      ec_invm (z1, p1_.z, ctx);
-	      ec_mulm (result->x, p1_.x, z1, ctx);
-	      mpi_set_ui (result->z, 1);
-	    }
-        }
+      sw = (nbits & 1);
+      mpi_swap_conditional (p1.x, p1_.x, sw);
+      mpi_swap_conditional (p1.y, p1_.y, sw);
+      mpi_swap_conditional (p1.z, p1_.z, sw);
+
+      if (p1.z->nlimbs == 0)
+	{
+	  mpi_set_ui (result->x, 1);
+	  mpi_set_ui (result->z, 0);
+	}
       else
-        {
-	  if (p1.z->nlimbs == 0)
-	    {
-	      mpi_set_ui (result->x, 1);
-	      mpi_set_ui (result->z, 0);
-	    }
-	  else
-	    {
-	      ec_invm (z1, p1.z, ctx);
-	      ec_mulm (result->x, p1.x, z1, ctx);
-	      mpi_set_ui (result->z, 1);
-	    }
-        }
+	{
+	  ec_invm (z1, p1.z, ctx);
+	  ec_mulm (result->x, p1.x, z1, ctx);
+	  mpi_set_ui (result->z, 1);
+	}
 
       mpi_free (z1);
       point_free (&p1);

commit 8823785c0285354425051d881a9446ecbbec329d
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jun 19 14:45:51 2014 +0900

    mpi_swap_conditional

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index d59c095..91d9d8f 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4341,6 +4341,11 @@ small values (usually up to the word size of the CPU).
 Swap the values of @var{a} and @var{b}.
 @end deftypefun
 
+ at deftypefun void gcry_mpi_swap_conditional (@w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}}, @w{unsigned long @var{sw}})
+
+Swap the values of @var{a} and @var{b}, when @var{sw} is 1.
+ at end deftypefun
+
 @deftypefun void gcry_mpi_snatch (@w{gcry_mpi_t @var{w}}, @
                                   @w{const gcry_mpi_t @var{u}})
 
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index fdce578..e0afec0 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -541,6 +541,43 @@ _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
     tmp = *a; *a = *b; *b = tmp;
 }
 
+void
+_gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
+{
+  size_t i;
+  size_t nlimbs = a->nlimbs;
+  unsigned long mask = -(long)swap;
+
+  if (b->alloced < a->nlimbs)
+    {
+      mpi_resize (b, a->nlimbs);
+      nlimbs = a->nlimbs;
+    }
+  else if (a->alloced < b->nlimbs)
+    {
+      mpi_resize (a, b->nlimbs);
+      nlimbs = b->nlimbs;
+    }
+  else if (b->nlimbs < a->nlimbs)
+    {
+      mpi_resize (b, a->nlimbs);
+      nlimbs = b->nlimbs = a->nlimbs;
+    }
+  else if (a->nlimbs < b->nlimbs)
+    {
+      mpi_resize (a, b->nlimbs);
+      nlimbs = a->nlimbs = b->nlimbs;
+    }
+
+  for (i = 0; i < nlimbs; i++)
+    {
+      unsigned long x = mask & (a->d[i] ^ b->d[i]);
+      a->d[i] = a->d[i] ^ x;
+      b->d[i] = b->d[i] ^ x;
+    }
+}
+
+
 
 gcry_mpi_t
 _gcry_mpi_new (unsigned int nbits)
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 8a6df84..42b72d6 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -371,6 +371,7 @@ gcry_mpi_t _gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
 gcry_mpi_t _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
 gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u);
 void _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
+void _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
 int _gcry_mpi_is_neg (gcry_mpi_t a);
 void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
 void _gcry_mpi_abs (gcry_mpi_t w);
@@ -475,6 +476,7 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
 #define mpi_set_ui( w, u)      _gcry_mpi_set_ui( (w), (u) )
 #define mpi_get_ui(a,b)        _gcry_mpi_get_ui( (a), (b) )
 #define mpi_swap(a,b)          _gcry_mpi_swap ((a),(b))
+#define mpi_swap_conditional(a,b,sw)          _gcry_mpi_swap_conditional ((a),(b),(sw))
 #define mpi_abs( w )           _gcry_mpi_abs( (w) )
 #define mpi_neg( w, u)         _gcry_mpi_neg( (w), (u) )
 #define mpi_cmp( u, v )        _gcry_mpi_cmp( (u), (v) )
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index a5f8350..f9bd166 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -545,6 +545,9 @@ gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
 /* Swap the values of A and B. */
 void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
 
+/* Swap the values of A and B if SW is 1. */
+void gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
+
 /* Return 1 if A is negative; 0 if zero or positive.  */
 int gcry_mpi_is_neg (gcry_mpi_t a);
 
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 57ed490..aee85ac 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -276,5 +276,6 @@ EXPORTS
       gcry_mac_ctl              @242
       gcry_mac_get_algo         @243
 
+      gcry_mpi_swap_conditional @244
 
 ;; end of file with public symbols for Windows.
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 7ee0541..0540850 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -96,7 +96,7 @@ GCRYPT_1.6 {
     gcry_mpi_set_flag; gcry_mpi_set_highbit;
     gcry_mpi_set_opaque; gcry_mpi_set_opaque_copy;
     gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui;
-    gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit;
+    gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_swap_conditional; gcry_mpi_test_bit;
     gcry_mpi_lshift; gcry_mpi_snatch;
     gcry_mpi_point_new; gcry_mpi_point_release;
     gcry_mpi_point_get; gcry_mpi_point_snatch_get;
diff --git a/src/mpi.h b/src/mpi.h
index eb0730e..7859dec 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -125,6 +125,7 @@ gcry_mpi_t  _gcry_mpi_alloc_like( gcry_mpi_t a );
 gcry_mpi_t  _gcry_mpi_alloc_set_ui( unsigned long u);
 void _gcry_mpi_m_check( gcry_mpi_t a );
 void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b);
+void _gcry_mpi_swap_conditional(gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
 gcry_mpi_t _gcry_mpi_new (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_snew (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a,
diff --git a/src/visibility.c b/src/visibility.c
index 6ed57ca..ec3b644 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -319,6 +319,12 @@ gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
   _gcry_mpi_swap (a, b);
 }
 
+void
+gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw)
+{
+  _gcry_mpi_swap_conditional (a, b, sw);
+}
+
 int
 gcry_mpi_is_neg (gcry_mpi_t a)
 {
diff --git a/src/visibility.h b/src/visibility.h
index 96b5235..54767e3 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -266,6 +266,7 @@ MARK_VISIBLEX (gcry_mpi_sub)
 MARK_VISIBLEX (gcry_mpi_sub_ui)
 MARK_VISIBLEX (gcry_mpi_subm)
 MARK_VISIBLEX (gcry_mpi_swap)
+MARK_VISIBLEX (gcry_mpi_swap_conditional)
 MARK_VISIBLEX (gcry_mpi_test_bit)
 
 MARK_VISIBLEX (gcry_ctx_release)
@@ -482,6 +483,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_mpi_sub_ui             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_subm               _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_swap               _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_mpi_swap_conditional   _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_test_bit           _gcry_USE_THE_UNDERSCORED_FUNCTION
 
 #define gcry_mpi_abs                _gcry_USE_THE_UNDERSCORED_FUNCTION

commit f88f67e08cccb60e2645743b3510ccde5f469818
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jun 13 15:49:22 2014 +0900

    Handle O in _gcry_mpi_ec_mul_point for MPI_EC_MONTGOMERY.

diff --git a/mpi/ec.c b/mpi/ec.c
index ae2d6fa..b312f53 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1236,17 +1236,33 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 
       z1 = mpi_new (0);
       mpi_clear (result->y);
-      mpi_set_ui (result->z, 1);
       if ((nbits & 1))
         {
-          ec_invm (z1, p1_.z, ctx);
-          ec_mulm (result->x, p1_.x, z1, ctx);
-          mpi_clear (result->y);
+	  if (p1_.z->nlimbs == 0)
+	    {
+	      mpi_set_ui (result->x, 1);
+	      mpi_set_ui (result->z, 0);
+	    }
+	  else
+	    {
+	      ec_invm (z1, p1_.z, ctx);
+	      ec_mulm (result->x, p1_.x, z1, ctx);
+	      mpi_set_ui (result->z, 1);
+	    }
         }
       else
         {
-          ec_invm (z1, p1.z, ctx);
-          ec_mulm (result->x, p1.x, z1, ctx);
+	  if (p1.z->nlimbs == 0)
+	    {
+	      mpi_set_ui (result->x, 1);
+	      mpi_set_ui (result->z, 0);
+	    }
+	  else
+	    {
+	      ec_invm (z1, p1.z, ctx);
+	      ec_mulm (result->x, p1.x, z1, ctx);
+	      mpi_set_ui (result->z, 1);
+	    }
         }
 
       mpi_free (z1);
@@ -1378,8 +1394,12 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
       }
       break;
     case MPI_EC_MONTGOMERY:
+#if 0
       log_fatal ("%s: %s not yet supported\n",
                  "_gcry_mpi_ec_curve_point", "Montgomery");
+#else
+      res = 1;
+#endif
       break;
     case MPI_EC_EDWARDS:
       {
diff --git a/tests/curves.c b/tests/curves.c
index 5dc9d6d..ae699d4 100644
--- a/tests/curves.c
+++ b/tests/curves.c
@@ -103,6 +103,42 @@ die (const char *format, ...)
 }
 
 
+static gcry_mpi_t
+hex2mpi (const char *string)
+{
+  gpg_error_t err;
+  gcry_mpi_t val;
+
+  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+  if (err)
+    die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
+  return val;
+}
+
+
+/* Print an MPI S-expression.  */
+static void
+print_mpi (const char *name, gcry_mpi_t a)
+{
+  gcry_error_t err;
+  unsigned char *buf;
+  int writerr = 0;
+
+  err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a);
+  if (err)
+    die ("gcry_mpi_aprint failed: %s\n", gcry_strerror (err));
+
+  printf ("  (%s #%s#)\n", name, buf);
+  if (ferror (stdout))
+    writerr++;
+  if (!writerr && fflush (stdout) == EOF)
+    writerr++;
+  if (writerr)
+    die ("writing output failed\n");
+  gcry_free (buf);
+}
+
+
 static void
 list_curves (void)
 {

commit 9fc9a91b9746cc0617fc73bd3146cf7be1e7c1b5
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Apr 25 09:04:24 2014 +0900

    for macos

diff --git a/mpi/config.links b/mpi/config.links
index 0217d35..4f35ea2 100644
--- a/mpi/config.links
+++ b/mpi/config.links
@@ -127,6 +127,12 @@ case "${host}" in
 	path="i586 i386"
         mpi_cpu_arch="x86"
 	;;
+    x86_64-apple-darwin*)
+	echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h
+	cat  $srcdir/mpi/i386/syntax.h	    >>./mpi/asm-syntax.h
+	path="amd64"
+        mpi_cpu_arch="x86"
+	;;
     x86_64-*-*)
 	echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
 	cat  $srcdir/mpi/i386/syntax.h	    >>./mpi/asm-syntax.h

commit 8669cebc8f67e80d614e5e520bbac0f60a88d85c
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Apr 25 09:04:10 2014 +0900

    more montgomery

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index f4945e5..e7dbc17 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -135,7 +135,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x01DB41",
       "0x01",
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
-      "0x09",
+      "0x0000000000000000000000000000000000000000000000000000000000000009",
       "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"
     },
 #if 0 /* No real specs yet found.  */
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 3f284fe..595aa0c 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -202,8 +202,13 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
     }
   if (*buf != 4)
     {
+      /* x-coordinate only */
+      mpi_set (result->x, value);
+      mpi_clear (result->y);
+      mpi_set_ui (result->z, 1);
+
       xfree (buf_memory);
-      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
+      return 0;
     }
   if ( ((n-1)%2) )
     {
diff --git a/cipher/ecc.c b/cipher/ecc.c
index e0be2d4..6a60785 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -117,7 +117,25 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&Q);
 
   /* Generate a secret.  */
-  if (ctx->dialect == ECC_DIALECT_ED25519)
+  /*
+   * FIXME.  It should be something like this:
+   *
+   *   When the co-factor of the curve is not 1, we guarantee that
+   *   scalar value k is multiple of its co-factor to avoid sub-group
+   *   attack.  Also, we make sure that the most significant bit of k
+   *   is 1.
+   *
+   * It works for now as we only have two curves which have co-factor!=1;
+   * Ed25519 and Curve25519.
+   * Note that we need some a way to get number of bits of the curve to
+   * set MSB of k.  Currently, E.nbits is not precise for this purpuse.
+   * We also need a way to get co-factor of a curve.
+   *
+   * Currently, we distinguish the two curves by ECC_DIALECT_ED25519
+   * and MPI_EC_MONTGOMERY, which works, but is not that correct.
+   */
+  if (ctx->dialect == ECC_DIALECT_ED25519
+      || E->model == MPI_EC_MONTGOMERY)
     {
       char *rndbuf;
 
@@ -156,7 +174,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * possibilities without any loss of security.  Note that we don't
    * do that for Ed25519 so that we do not violate the special
    * construction of the secret key.  */
-  if (E->dialect == ECC_DIALECT_ED25519)
+  if (E->dialect == ECC_DIALECT_ED25519 || E->model == MPI_EC_MONTGOMERY)
     point_set (&sk->Q, &Q);
   else
     {
@@ -227,12 +245,8 @@ static void
 test_keys (ECC_secret_key *sk, unsigned int nbits)
 {
   ECC_public_key pk;
-  gcry_mpi_t test = mpi_new (nbits);
+  gcry_mpi_t test;
   mpi_point_struct R_;
-  gcry_mpi_t c = mpi_new (nbits);
-  gcry_mpi_t out = mpi_new (nbits);
-  gcry_mpi_t r = mpi_new (nbits);
-  gcry_mpi_t s = mpi_new (nbits);
 
   if (DBG_CIPHER)
     log_debug ("Testing key.\n");
@@ -243,27 +257,82 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
   point_init (&pk.Q);
   point_set (&pk.Q, &sk->Q);
 
-  _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
+  if (sk->E.model == MPI_EC_MONTGOMERY)
+    /* It's ECDH only. */
+    /* FIXME: see the FIXME comment of nist_generate_key.
+     * Here, we generate ephemeral key, same handling is needed for secret.
+     */
+    {
+      char *rndbuf;
+      gcry_mpi_t x0, x1;
+      mpi_ec_t ec;
+
+      test = mpi_new (256);
+      rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM);
+      rndbuf[0] &= 0x7f;  /* Clear bit 255. */
+      rndbuf[0] |= 0x40;  /* Set bit 254.   */
+      rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0  */
+      _gcry_mpi_set_buffer (test, rndbuf, 32, 0);
+      xfree (rndbuf);
+
+      ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
+                                        pk.E.p, pk.E.a, pk.E.b);
+      x0 = mpi_new (0);
+      x1 = mpi_new (0);
 
-  if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
-    log_fatal ("ECDSA operation: sign failed\n");
+      /* R_ = kQ  <=>  R_ = kdG  */
+      _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
+      if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec))
+          log_fatal ("ecdh: Failed to get affine coordinates for kQ\n");
 
-  if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
-    {
-      log_fatal ("ECDSA operation: sign, verify failed\n");
+      /* R_ = kG */
+      _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec);
+      /* R_ = dkG */
+      _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec);
+
+      if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
+        log_fatal ("ecdh: Failed to get affine coordinates for dkG\n");
+
+      if (mpi_cmp (x0, x1))
+        {
+          log_fatal ("ECDH test failed.\n");
+        }
+
+      mpi_free (x0);
+      mpi_free (x1);
+      _gcry_mpi_ec_free (ec);
     }
+  else
+    {
+      gcry_mpi_t c = mpi_new (nbits);
+      gcry_mpi_t out = mpi_new (nbits);
+      gcry_mpi_t r = mpi_new (nbits);
+      gcry_mpi_t s = mpi_new (nbits);
 
-  if (DBG_CIPHER)
-    log_debug ("ECDSA operation: sign, verify ok.\n");
+      test = mpi_new (nbits);
+      _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
+
+      if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
+        log_fatal ("ECDSA operation: sign failed\n");
+
+      if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+        {
+          log_fatal ("ECDSA operation: sign, verify failed\n");
+        }
+
+      if (DBG_CIPHER)
+        log_debug ("ECDSA operation: sign, verify ok.\n");
+
+      mpi_free (s);
+      mpi_free (r);
+      mpi_free (out);
+      mpi_free (c);
+    }
 
   point_free (&pk.Q);
   _gcry_ecc_curve_free (&pk.E);
 
   point_free (&R_);
-  mpi_free (s);
-  mpi_free (r);
-  mpi_free (out);
-  mpi_free (c);
   mpi_free (test);
 }
 
diff --git a/mpi/ec.c b/mpi/ec.c
index 1257bbe..ae2d6fa 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -600,15 +600,11 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
 
     case MPI_EC_MONTGOMERY:
       {
-        gcry_mpi_t z1;
-
-        z1 = mpi_new (0);
-        ec_invm (z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
-
         if (x)
-          ec_mulm (x, point->x, z1, ctx);
+          mpi_set (x, point->x);
 
-        mpi_free (z1);
+        if (y)
+          mpi_set (y, point->y);
       }
       return 0;
 
@@ -1238,19 +1234,22 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
           dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
         }
 
+      z1 = mpi_new (0);
+      mpi_clear (result->y);
+      mpi_set_ui (result->z, 1);
       if ((nbits & 1))
         {
-          mpi_snatch (result->x, p1_.x);
-          mpi_snatch (result->z, p1_.z);
-          p1_.x = p1_.z = NULL;
+          ec_invm (z1, p1_.z, ctx);
+          ec_mulm (result->x, p1_.x, z1, ctx);
+          mpi_clear (result->y);
         }
       else
         {
-          mpi_snatch (result->x, p1.x);
-          mpi_snatch (result->z, p1.z);
-          p1.x = p1.z = NULL;
+          ec_invm (z1, p1.z, ctx);
+          ec_mulm (result->x, p1.x, z1, ctx);
         }
 
+      mpi_free (z1);
       point_free (&p1);
       point_free (&p2);
       point_free (&p1_);
diff --git a/tests/curves.c b/tests/curves.c
index 29654f3..5dc9d6d 100644
--- a/tests/curves.c
+++ b/tests/curves.c
@@ -205,6 +205,11 @@ check_montgomery (void)
   const char *name;
   unsigned int nbits;
 
+  gcry_ctx_t ctx;
+  gcry_mpi_point_t G, Q;
+  gcry_mpi_t d;
+  gcry_mpi_t x, y, z;
+
   err = gcry_sexp_new (&key, sample_key_3, 0, 1);
   if (err)
     die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
@@ -219,6 +224,56 @@ check_montgomery (void)
           sample_key_3_nbits, nbits);
 
   gcry_sexp_release (key);
+
+  Q = gcry_mpi_point_new (0);
+
+  err = gcry_mpi_ec_new (&ctx, NULL, "Curve25519");
+  if (err)
+    fail ("can't create ec context: %s\n", gpg_strerror (err));
+
+#if 0
+  d = hex2mpi ("40000000000000000000000000000000"
+               "00000000000000000000000000000000");
+  G = gcry_mpi_ec_get_point ("g", ctx, 1);
+  if (!G)
+    fail ("can't get basepoint of the curve: %s\n", gpg_strerror (err));
+#else
+  d = hex2mpi ("7d74fb61db3100e11e4d4ae171daf820688f3bcfa631565272a998b8f4e8c290");
+  {
+    gcry_mpi_t gx;
+    gx = hex2mpi ("3dc16d73d4222d12eb54623c85f3fb5ebdab33c1bd5865780654f1b0ed696ddf");
+
+    G = gcry_mpi_point_new (0);
+    gcry_mpi_point_snatch_set (G, gx, NULL, NULL);
+  }
+#endif
+
+  gcry_mpi_ec_mul (Q, d, G, ctx);
+
+  x = gcry_mpi_new (0);
+  y = gcry_mpi_new (0);
+  z = gcry_mpi_new (0);
+
+  gcry_mpi_point_get (x, y, z, Q);
+
+  print_mpi ("Q.x", x);
+  print_mpi ("Q.y", y);
+  print_mpi ("Q.z", z);
+
+  if (gcry_mpi_ec_get_affine (x, NULL, Q, ctx))
+    fail ("failed to get affine coordinates\n");
+
+  print_mpi ("q.x", x);
+  /* 16B53A046DEEDD81ED6B0D470CE46DD9B5FAC6124F3D22358AA7CD2911FCFABC */
+
+  gcry_mpi_release (z);
+  gcry_mpi_release (y);
+  gcry_mpi_release (x);
+
+  gcry_mpi_point_release (Q);
+  gcry_mpi_release (d);
+  gcry_mpi_point_release (G);
+  gcry_ctx_release (ctx);
 }
 
 int
diff --git a/tests/keygen.c b/tests/keygen.c
index 4aff9c9..c53246c 100644
--- a/tests/keygen.c
+++ b/tests/keygen.c
@@ -365,7 +365,7 @@ static void
 check_ecc_keys (void)
 {
   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
-                           "Ed25519", NULL };
+                           "Ed25519", "Curve25519", NULL };
   int testno;
   gcry_sexp_t keyparm, key;
   int rc;

commit 9f2da5436af53e913cdccd01e83523ab3cc38475
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Apr 22 15:31:24 2014 +0900

    support ec_get_affine

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 6a90eaf..f4945e5 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -132,10 +132,10 @@ static const ecc_domain_parms_t domain_parms[] =
       "Curve25519", 256, 0,
       MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
-      "0X1DB41",
-      "0x1",
+      "0x01DB41",
+      "0x01",
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
-      "0x9",
+      "0x09",
       "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"
     },
 #if 0 /* No real specs yet found.  */
@@ -518,9 +518,8 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
     {
     case MPI_EC_WEIERSTRASS:
     case MPI_EC_EDWARDS:
-      break;
     case MPI_EC_MONTGOMERY:
-      return GPG_ERR_NOT_SUPPORTED;
+      break;
     default:
       return GPG_ERR_BUG;
     }
diff --git a/mpi/ec.c b/mpi/ec.c
index c4ac819..1257bbe 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -600,10 +600,17 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
 
     case MPI_EC_MONTGOMERY:
       {
-        log_fatal ("%s: %s not yet supported\n",
-                   "_gcry_mpi_ec_get_affine", "Montgomery");
+        gcry_mpi_t z1;
+
+        z1 = mpi_new (0);
+        ec_invm (z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
+
+        if (x)
+          ec_mulm (x, point->x, z1, ctx);
+
+        mpi_free (z1);
       }
-      return -1;
+      return 0;
 
     case MPI_EC_EDWARDS:
       {
@@ -1095,7 +1102,7 @@ dup_and_add_montgomery (mpi_point_t prd, mpi_point_t sum,
   ec_subm (p1->z, p1->x, p1->z, ctx);
   ec_pow2 (sum->x, sum->x, ctx);
   ec_pow2 (sum->z, p2->z, ctx);
-  ec_mulm (prd->z, p1->z, ctx->a, ctx);	/* ctx->a: (A-2)/4 */
+  ec_mulm (prd->z, p1->z, ctx->a, ctx); /* ctx->a: (A-2)/4 */
   ec_mulm (sum->z, sum->z, dif_x, ctx);
   ec_addm (prd->z, p1->x, prd->z, ctx);
   ec_mulm (prd->z, prd->z, p1->z, ctx);
@@ -1181,65 +1188,68 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 
       nbits = mpi_get_nbits (scalar);
       point_init (&p1);
-      mpi_set_ui (p1.x, 1);
-      p2.x  = mpi_copy (scalar);
-      p2.y = mpi_new (0);
-      p2.z = mpi_new (1);
+      point_init (&p2);
       point_init (&p1_);
       point_init (&p2_);
+      mpi_set_ui (p1.x, 1);
+      mpi_free (p2.x);
+      p2.x  = mpi_copy (point->x);
+      mpi_set_ui (p2.z, 1);
 
       for (j=nbits-1; j >= 0; j--)
-	{
-	  mpi_point_t q1, q2;
-	  mpi_point_t sum_n, prd_n;
-
-	  if (mpi_test_bit (scalar, j))
-	    {
-	      q1 = &p2;
-	      q2 = &p1;
-	      sum_n = &p1_;
-	      prd_n = &p2_;
-	    }
-	  else
-	    {
-	      q1 = &p1;
-	      q2 = &p2;
-	      sum_n = &p2_;
-	      prd_n = &p1_;
-	    }
-	  dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
-
-	  if (--j < 0)
-	    break;
-
-	  if (mpi_test_bit (scalar, j))
-	    {
-	      q1 = &p2_;
-	      q2 = &p1_;
-	      sum_n = &p1;
-	      prd_n = &p2;
-	    }
-	  else
-	    {
-	      q1 = &p1_;
-	      q2 = &p2_;
-	      sum_n = &p2;
-	      prd_n = &p1;
-	    }
-
-	  dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
-	}
+        {
+          mpi_point_t q1, q2;
+          mpi_point_t sum_n, prd_n;
+
+          if (mpi_test_bit (scalar, j))
+            {
+              q1 = &p2;
+              q2 = &p1;
+              sum_n = &p1_;
+              prd_n = &p2_;
+            }
+          else
+            {
+              q1 = &p1;
+              q2 = &p2;
+              sum_n = &p2_;
+              prd_n = &p1_;
+            }
+          dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+
+          if (--j < 0)
+            break;
+
+          if (mpi_test_bit (scalar, j))
+            {
+              q1 = &p2_;
+              q2 = &p1_;
+              sum_n = &p1;
+              prd_n = &p2;
+            }
+          else
+            {
+              q1 = &p1_;
+              q2 = &p2_;
+              sum_n = &p2;
+              prd_n = &p1;
+            }
+
+          dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+        }
 
       if ((nbits & 1))
-	{
-	  ec_invm (result->x, p1_.z, ctx);
-	  ec_mulm (result->x, result->x, p1_.x, ctx);
-	}
+        {
+          mpi_snatch (result->x, p1_.x);
+          mpi_snatch (result->z, p1_.z);
+          p1_.x = p1_.z = NULL;
+        }
       else
-	{
-	  ec_invm (result->x, p1.z, ctx);
-	  ec_mulm (result->x, result->x, p1.x, ctx);
-	}
+        {
+          mpi_snatch (result->x, p1.x);
+          mpi_snatch (result->z, p1.z);
+          p1.x = p1.z = NULL;
+        }
 
       point_free (&p1);
       point_free (&p2);

commit a2b17d3639b7abb55decb67afbf8561a544c1cd7
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Apr 18 18:38:15 2014 +0900

    Add Curve25519

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 0f622f7..6a90eaf 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -40,7 +40,7 @@ static const struct
   const char *other; /* Other name. */
 } curve_aliases[] =
   {
-  /*{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },*/
+    { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
     { "Ed25519",    "1.3.6.1.4.1.11591.15.1" },
 
     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
@@ -127,6 +127,17 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
       "0x6666666666666666666666666666666666666666666666666666666666666658"
     },
+    {
+      /* (y^2 = x^3 + 486662*x^2 + x) */
+      "Curve25519", 256, 0,
+      MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
+      "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
+      "0X1DB41",
+      "0x1",
+      "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
+      "0x9",
+      "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"
+    },
 #if 0 /* No real specs yet found.  */
     {
       /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
diff --git a/mpi/ec.c b/mpi/ec.c
index 4f35de0..c4ac819 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1073,6 +1073,35 @@ add_points_edwards (mpi_point_t result,
 }
 
 
+/* PRD = 2 * P1.
+   SUM = P1 + P2.
+   P1 - P2 = DIF  */
+static void
+dup_and_add_montgomery (mpi_point_t prd, mpi_point_t sum,
+                        mpi_point_t p1, mpi_point_t p2, gcry_mpi_t dif_x,
+                        mpi_ec_t ctx)
+{
+  ec_addm (sum->x, p2->x, p2->z, ctx);
+  ec_subm (p2->z, p2->x, p2->z, ctx);
+  ec_addm (prd->x, p1->x, p1->z, ctx);
+  ec_subm (p1->z, p1->x, p1->z, ctx);
+  ec_mulm (p2->x, p1->z, sum->x, ctx);
+  ec_mulm (p2->z, prd->x, p2->z, ctx);
+  ec_pow2 (p1->x, prd->x, ctx);
+  ec_pow2 (p1->z, p1->z, ctx);
+  ec_addm (sum->x, p2->x, p2->z, ctx);
+  ec_subm (p2->z, p2->x, p2->z, ctx);
+  ec_mulm (prd->x, p1->x, p1->z, ctx);
+  ec_subm (p1->z, p1->x, p1->z, ctx);
+  ec_pow2 (sum->x, sum->x, ctx);
+  ec_pow2 (sum->z, p2->z, ctx);
+  ec_mulm (prd->z, p1->z, ctx->a, ctx);	/* ctx->a: (A-2)/4 */
+  ec_mulm (sum->z, sum->z, dif_x, ctx);
+  ec_addm (prd->z, p1->x, prd->z, ctx);
+  ec_mulm (prd->z, prd->z, p1->z, ctx);
+}
+
+
 /* RESULT = P1 + P2 */
 void
 _gcry_mpi_ec_add_points (mpi_point_t result,
@@ -1144,6 +1173,80 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
         }
       return;
     }
+  else if (ctx->model == MPI_EC_MONTGOMERY)
+    {
+      unsigned int nbits;
+      int j;
+      mpi_point_struct p1_, p2_;
+
+      nbits = mpi_get_nbits (scalar);
+      point_init (&p1);
+      mpi_set_ui (p1.x, 1);
+      p2.x  = mpi_copy (scalar);
+      p2.y = mpi_new (0);
+      p2.z = mpi_new (1);
+      point_init (&p1_);
+      point_init (&p2_);
+
+      for (j=nbits-1; j >= 0; j--)
+	{
+	  mpi_point_t q1, q2;
+	  mpi_point_t sum_n, prd_n;
+
+	  if (mpi_test_bit (scalar, j))
+	    {
+	      q1 = &p2;
+	      q2 = &p1;
+	      sum_n = &p1_;
+	      prd_n = &p2_;
+	    }
+	  else
+	    {
+	      q1 = &p1;
+	      q2 = &p2;
+	      sum_n = &p2_;
+	      prd_n = &p1_;
+	    }
+	  dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+
+	  if (--j < 0)
+	    break;
+
+	  if (mpi_test_bit (scalar, j))
+	    {
+	      q1 = &p2_;
+	      q2 = &p1_;
+	      sum_n = &p1;
+	      prd_n = &p2;
+	    }
+	  else
+	    {
+	      q1 = &p1_;
+	      q2 = &p2_;
+	      sum_n = &p2;
+	      prd_n = &p1;
+	    }
+
+	  dup_and_add_montgomery (prd_n, sum_n, q1, q2, point->x, ctx);
+	}
+
+      if ((nbits & 1))
+	{
+	  ec_invm (result->x, p1_.z, ctx);
+	  ec_mulm (result->x, result->x, p1_.x, ctx);
+	}
+      else
+	{
+	  ec_invm (result->x, p1.z, ctx);
+	  ec_mulm (result->x, result->x, p1.x, ctx);
+	}
+
+      point_free (&p1);
+      point_free (&p2);
+      point_free (&p1_);
+      point_free (&p2_);
+      return;
+    }
 
   x1 = mpi_alloc_like (ctx->p);
   y1 = mpi_alloc_like (ctx->p);
diff --git a/tests/curves.c b/tests/curves.c
index 0581452..29654f3 100644
--- a/tests/curves.c
+++ b/tests/curves.c
@@ -29,7 +29,7 @@
 #include "../src/gcrypt-int.h"
 
 /* Number of curves defined in ../cipger/ecc.c */
-#define N_CURVES 21
+#define N_CURVES 22
 
 /* A real world sample public key.  */
 static char const sample_key_1[] =
@@ -64,6 +64,18 @@ static char const sample_key_2_curve[] = "brainpoolP160r1";
 static unsigned int sample_key_2_nbits = 160;
 
 
+/* Another sample public key.  */
+static char const sample_key_3[] =
+"(public-key\n"
+" (ecdh\n"
+"  (curve Curve25519)\n"
+"  (q #040000000000000000000000000000000000000000000000000000000000000000"
+"        0000000000000000000000000000000000000000000000000000000000000000#)\n"
+"  ))";
+static char const sample_key_3_curve[] = "Curve25519";
+static unsigned int sample_key_3_nbits = 256;
+
+
 /* Program option flags.  */
 static int verbose;
 static int error_count;
@@ -185,6 +197,30 @@ check_get_params (void)
 }
 
 
+static void
+check_montgomery (void)
+{
+  gpg_error_t err;
+  gcry_sexp_t key;
+  const char *name;
+  unsigned int nbits;
+
+  err = gcry_sexp_new (&key, sample_key_3, 0, 1);
+  if (err)
+    die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
+  name = gcry_pk_get_curve (key, 0, &nbits);
+  if (!name)
+    fail ("curve name not found for sample_key_3\n");
+  else if (strcmp (name, sample_key_3_curve))
+    fail ("expected curve name %s but got %s for sample_key_3\n",
+          sample_key_3_curve, name);
+  else if (nbits != sample_key_3_nbits)
+    fail ("expected curve size %u but got %u for sample_key_3\n",
+          sample_key_3_nbits, nbits);
+
+  gcry_sexp_release (key);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -205,6 +241,7 @@ main (int argc, char **argv)
   list_curves ();
   check_matching ();
   check_get_params ();
+  check_montgomery ();
 
   return error_count ? 1 : 0;
 }

-----------------------------------------------------------------------


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org




More information about the Gnupg-commits mailing list