Nils Durner | 18 Aug 09:24 2014

libgpg-error FTBS on MinGW

Hi,

libgpg-error 1.13 fails to build on MinGW(.org): http://pastebin.com/BBsRLYJp
config.log: http://pastebin.com/kVa5Bp6z

Apologies if this has already been fixed. Please CC answers to the sender address as I am not subscribed to the mailing list.


Best regards,

Nils Durner
_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
NIIBE Yutaka | 12 Aug 09:56 2014

[PATCH] ecc: Support Montgomery curve (1)

Hello,

This patch is improving support of Montgomery curve.

    * Enable MPI_EC_MONTGOMERY in _gcry_ecc_fill_in_curve

    * Since test_keys checks keys by ecdsa/eddsa, new function
      test_ecdh_only_keys which checks keys by ecdh is added.

    * Handle MPI_EC_MONTGOMERY in check_secret_key

It also includes fixes for my mistakes:

    * TAB characters in compute_keygrip.
    * mpi_resize in _gcry_mpi_ec_mul_point and code clean up.

With this patch, Montgomery curve is not fully supported yet, we need
to fix its support for encoding/decoding key, key generation, and
encrypt/decrypt.

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index fd47c1d..9975bb4 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
 <at>  <at>  -530,9 +530,8  <at>  <at>  _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/cipher/ecc.c b/cipher/ecc.c
index 8bdbd56..fa219fb 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
 <at>  <at>  -81,6 +81,7  <at>  <at>  static void *progress_cb_data;
 
 /* Local prototypes. */
 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
+static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits);
 static unsigned int ecc_get_nbits (gcry_sexp_t parms);

 <at>  <at>  -209,7 +210,10  <at>  <at>  nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,

   point_free (&Q);
   /* Now we can test our keys (this should never fail!).  */
-  test_keys (sk, nbits - 64);
+  if (sk->E.model != MPI_EC_MONTGOMERY)
+    test_keys (sk, nbits - 64);
+  else
+    test_ecdh_only_keys (sk, nbits - 64);

   return 0;
 }
 <at>  <at>  -266,6 +270,80  <at>  <at>  test_keys (ECC_secret_key *sk, unsigned int nbits)
 }

+static void
+test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)
+{
+  ECC_public_key pk;
+  gcry_mpi_t test;
+  mpi_point_struct R_;
+  gcry_mpi_t x0, x1;
+  mpi_ec_t ec;
+
+  if (DBG_CIPHER)
+    log_debug ("Testing key.\n");
+
+  point_init (&R_);
+
+  pk.E = _gcry_ecc_curve_copy (sk->E);
+  point_init (&pk.Q);
+  point_set (&pk.Q, &sk->Q);
+
+  if (sk->E.dialect == ECC_DIALECT_ED25519)
+    {
+      char *rndbuf;
+
+      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);
+    }
+  else
+    {
+      test = mpi_new (nbits);
+      _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
+    }
+
+  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);
+
+  /* R_ = hkQ  <=>  R_ = hkdG  */
+  _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
+  if (sk->E.dialect != ECC_DIALECT_ED25519)
+    _gcry_mpi_ec_mul_point (&R_, ec->h, &R, ec);
+  if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec))
+    log_fatal ("ecdh: Failed to get affine coordinates for hkQ\n");
+
+  _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec);
+  _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec);
+  /* R_ = hdkG */
+  if (sk->E.dialect != ECC_DIALECT_ED25519)
+    _gcry_mpi_ec_mul_point (&R_, ec->h, &R, ec);
+
+  if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
+    log_fatal ("ecdh: Failed to get affine coordinates for hdkG\n");
+
+  if (mpi_cmp (x0, x1))
+    {
+      log_fatal ("ECDH test failed.\n");
+    }
+
+  mpi_free (x0);
+  mpi_free (x1);
+  _gcry_mpi_ec_free (ec);
+
+  point_free (&pk.Q);
+  _gcry_ecc_curve_free (&pk.E);
+
+  point_free (&R_);
+  mpi_free (test);
+}
+
+
 /*
  * To check the validity of the value, recalculate the correspondence
  * between the public value and the secret one.
 <at>  <at>  -281,7 +359,10  <at>  <at>  check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)

   point_init (&Q);
   x1 = mpi_new (0);
-  y1 = mpi_new (0);
+  if (ec->model == MPI_EC_MONTGOMERY)
+    y1 = NULL;
+  else
+    y1 = mpi_new (0);

   /* G in E(F_p) */
   if (!_gcry_mpi_ec_curve_point (&sk->E.G, ec))
 <at>  <at>  -338,7 +419,7  <at>  <at>  check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
   else if (!mpi_cmp_ui (sk->Q.z, 1))
     {
       /* Fast path if Q is already in affine coordinates.  */
-      if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y1, sk->Q.y))
+      if (mpi_cmp (x1, sk->Q.x) || (!y1 && mpi_cmp (y1, sk->Q.y)))
         {
           if (DBG_CIPHER)
             log_debug
 <at>  <at>  -1581,7 +1662,7  <at>  <at>  compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
       char buf[30];

       if (idx == 5)
-	continue;		/* Skip cofactor. */
+        continue;               /* Skip cofactor. */

       if (mpi_is_opaque (values[idx]))
         {
diff --git a/mpi/ec.c b/mpi/ec.c
index a55291a..1f65a7c 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -1186,7 +1186,9  <at>  <at>  _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;

       /* Compute scalar point multiplication with Montgomery Ladder.
          Note that we don't use Y-coordinate in the points at all.
 <at>  <at>  -1202,27 +1204,35  <at>  <at>  _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_cond (p1.x, p2.x, sw);
-          mpi_swap_cond (p1.z, p2.z, sw);
-          montgomery_ladder (&p1_, &p2_, &p1, &p2, point->x, ctx);
-          mpi_swap_cond (p1_.x, p2_.x, sw);
-          mpi_swap_cond (p1_.z, p2_.z, sw);
-
-          if (--j < 0)
-            break;
+          mpi_point_t t;

           sw = mpi_test_bit (scalar, j);
-          mpi_swap_cond (p1_.x, p2_.x, sw);
-          mpi_swap_cond (p1_.z, p2_.z, sw);
-          montgomery_ladder (&p1, &p2, &p1_, &p2_, point->x, ctx);
-          mpi_swap_cond (p1.x, p2.x, sw);
-          mpi_swap_cond (p1.z, p2.z, sw);
+          mpi_swap_cond (q1->x, q2->x, sw);
+          mpi_swap_cond (q1->z, q2->z, sw);
+          montgomery_ladder (prd, sum, q1, q2, point->x, ctx);
+          mpi_swap_cond (prd->x, sum->x, sw);
+          mpi_swap_cond (prd->z, sum->z, sw);
+          t = q1;  q1 = prd;  prd = t;
+          t = q2;  q2 = sum;  sum = t;
         }

-      z1 = mpi_new (0);
       mpi_clear (result->y);
       sw = (nbits & 1);
       mpi_swap_cond (p1.x, p1_.x, sw);
 <at>  <at>  -1235,12 +1245,13  <at>  <at>  _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_);
--

-- 
by NIIBE Yutaka | 12 Aug 03:11 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-105-g34bb55e

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, master has been updated
       via  34bb55ee36df3aca3ebca88f8b61c786cd0c0701 (commit)
      from  e6d354865bf8f3d4c1bb5e8157a76fdd442cff41 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 34bb55ee36df3aca3ebca88f8b61c786cd0c0701
Author: NIIBE Yutaka <gniibe <at> fsij.org>
Date:   Tue Aug 12 10:03:39 2014 +0900

    ecc: Support Montgomery curve for gcry_mpi_ec_mul_point.

    * mpi/ec.c (_gcry_mpi_ec_get_affine): Support Montgomery curve.
    (montgomery_ladder): New.
    (_gcry_mpi_ec_mul_point): Implemention using montgomery_ladder.
    (_gcry_mpi_ec_curve_point): Check x-coordinate is valid.
    --

    Given Montgomery curve: b * y^2 == x^3 + a * x^2 + x
    CTX->A has (a-2)/4 and CTX->B has b^-1

    Note that _gcry_mpi_ec_add_points is not supported for this curve.

diff --git a/mpi/ec.c b/mpi/ec.c
index 737f12c..a55291a 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -601,10 +601,17  <at>  <at>  _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");
+        if (x)
+          mpi_set (x, point->x);
+
+        if (y)
+          {
+            log_fatal ("%s: Getting Y-coordinate on %s is not supported\n",
+                       "_gcry_mpi_ec_get_affine", "Montgomery");
+            return -1;
+          }
       }
-      return -1;
+      return 0;

     case MPI_EC_EDWARDS:
       {
 <at>  <at>  -1074,6 +1081,35  <at>  <at>  add_points_edwards (mpi_point_t result,
 }

 
+/* Compute a step of Montgomery Ladder (only use X and Z in the point).
+   Inputs:  P1, P2, and x-coordinate of DIF = P1 - P1.
+   Outputs: PRD = 2 * P1 and  SUM = P1 + P2. */
+static void
+montgomery_ladder (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,
 <at>  <at>  -1145,6 +1181,72  <at>  <at>  _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_;
+      unsigned long sw;
+
+      /* Compute scalar point multiplication with Montgomery Ladder.
+         Note that we don't use Y-coordinate in the points at all.
+         RESULT->Y will be filled by zero.  */
+
+      nbits = mpi_get_nbits (scalar);
+      point_init (&p1);
+      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--)
+        {
+          sw = mpi_test_bit (scalar, j);
+          mpi_swap_cond (p1.x, p2.x, sw);
+          mpi_swap_cond (p1.z, p2.z, sw);
+          montgomery_ladder (&p1_, &p2_, &p1, &p2, point->x, ctx);
+          mpi_swap_cond (p1_.x, p2_.x, sw);
+          mpi_swap_cond (p1_.z, p2_.z, sw);
+
+          if (--j < 0)
+            break;
+
+          sw = mpi_test_bit (scalar, j);
+          mpi_swap_cond (p1_.x, p2_.x, sw);
+          mpi_swap_cond (p1_.z, p2_.z, sw);
+          montgomery_ladder (&p1, &p2, &p1_, &p2_, point->x, ctx);
+          mpi_swap_cond (p1.x, p2.x, sw);
+          mpi_swap_cond (p1.z, p2.z, sw);
+        }
+
+      z1 = mpi_new (0);
+      mpi_clear (result->y);
+      sw = (nbits & 1);
+      mpi_swap_cond (p1.x, p1_.x, sw);
+      mpi_swap_cond (p1.z, p1_.z, sw);
+
+      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);
+      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);
 <at>  <at>  -1243,15 +1345,15  <at>  <at>  _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
   y = mpi_new (0);
   w = mpi_new (0);

-  if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
-    return 0;
-
   switch (ctx->model)
     {
     case MPI_EC_WEIERSTRASS:
       {
         gcry_mpi_t xxx = mpi_new (0);

+        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
+          return 0;
+
         /* y^2 == x^3 + a·x + b */
         ec_pow2 (y, y, ctx);

 <at>  <at>  -1267,11 +1369,40  <at>  <at>  _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
       }
       break;
     case MPI_EC_MONTGOMERY:
-      log_fatal ("%s: %s not yet supported\n",
-                 "_gcry_mpi_ec_curve_point", "Montgomery");
+      {
+#define xx y
+        /* With Montgomery curve, only X-coordinate is valid.  */
+        if (_gcry_mpi_ec_get_affine (x, NULL, point, ctx))
+          return 0;
+
+        /* The equation is: b * y^2 == x^3 + a · x^2 + x */
+        /* We check if right hand is quadratic residue or not by
+           Euler's criterion.  */
+        /* CTX->A has (a-2)/4 and CTX->B has b^-1 */
+        ec_mulm (w, ctx->a, mpi_const (MPI_C_FOUR), ctx);
+        ec_addm (w, w, mpi_const (MPI_C_TWO), ctx);
+        ec_mulm (w, w, x, ctx);
+        ec_pow2 (xx, x, ctx);
+        ec_addm (w, w, xx, ctx);
+        ec_addm (w, w, mpi_const (MPI_C_ONE), ctx);
+        ec_mulm (w, w, x, ctx);
+        ec_mulm (w, w, ctx->b, ctx);
+#undef xx
+        /* Compute Euler's criterion: w^(p-1)/2 */
+#define p_minus1 y
+        ec_subm (p_minus1, ctx->p, mpi_const (MPI_C_ONE), ctx);
+        mpi_rshift (p_minus1, p_minus1, 1);
+        ec_powm (w, w, p_minus1, ctx);
+
+        res = mpi_cmp_ui (w, 1);
+#undef p_minus1
+      }
       break;
     case MPI_EC_EDWARDS:
       {
+        if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
+          return 0;
+
         /* a · x^2 + y^2 - 1 - b · x^2 · y^2 == 0 */
         ec_pow2 (x, x, ctx);
         ec_pow2 (y, y, ctx);

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

Summary of changes:
 mpi/ec.c |  147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 139 insertions(+), 8 deletions(-)

hooks/post-receive
--

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

_______________________________________________
Gnupg-commits mailing list
Gnupg-commits <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Werner Koch | 12 Aug 00:00 2014
Picon

Re: AW: [Announce] [security fix] Libgcrypt and GnuPG

On Mon, 11 Aug 2014 13:21, edv <at> kommunalkredit.at said:

> please remove us from the mailing list. We are not longer using GnuPG in our company.

What about visiting the URL shown as last line of each mail send through
this mailing list?  Or looking into the list mail headers?

Shalom-Salam,

   Werner

--

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.
Werner Koch | 12 Aug 00:00 2014
Picon

Re: AW: [Announce] [security fix] Libgcrypt and GnuPG

On Mon, 11 Aug 2014 13:21, edv <at> kommunalkredit.at said:

> please remove us from the mailing list. We are not longer using GnuPG in our company.

What about visiting the URL shown as last line of each mail send through
this mailing list?  Or looking into the list mail headers?

Shalom-Salam,

   Werner

--

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.
Andreas Metzler | 10 Aug 11:49 2014
Picon

[patch] libgcrypt 1.5.4 error with texinfo 5.1

Good morning,

libgcrypt 1.5.x requires the attached patch for compatibility with
texinfo >= 5.1. Otherwise one gets these errors:

| /tmp/GCR/libgcrypt-1.5.4/doc/./gcrypt.texi:2015: Argument of  <at> asis has an extra
|  }.
| <inserted text>
|                  <at> par
| <to be read again>
|                    }
|  <at> doitemize ...1} <at> setbox 0 =  <at> hbox { <at> itemcontents }
|                                                    <at> ifx  <at> itemcontents  <at> empty ...
| l.2015  <at> itemize  <at> asis
| 
| ?

| [101] (/tmp/GCR/libgcrypt-1.5.4/doc/lgpl.texi
| (GNU Lesser General Public License) [102] [103] [104] [105] [106] [107]
| [108]
| /tmp/GCR/libgcrypt-1.5.4/doc/lgpl.texi:480: This command can appear only outsid
| e of any environment, not in environment  <at> enumerate.
|  <at> badenverr ...temp , not  <at> inenvironment  <at> thisenv }
| 
|  <at> checkenv ... <at> ifx  <at> thisenv  <at> temp  <at> else  <at> badenverr
|                                                    <at> fi
|  <at> sectionheading #1#2#3#4->{ <at> checkenv {}
|                                         <at> csname #2fonts <at> endcsname  <at> rmisbold  <at> ...
| 
|  <at> \heading ...tionheading {#1}{sec}{Yomitfromtoc}{}
|                                                     <at> suppressfirstparagraphin...
| l.480  <at> heading NO WARRANTY
| 
| ?

Patch originates from Ubuntu's libgcrypt11 (1.5.3-2ubuntu3) by
Matthias Klose <doko <at> ubuntu.com>.

I am sorry for forgetting to forward this earlier, in time for 1.5.4.

cu Andreas
--

-- 
`What a good friend you are to him, Dr. Maturin. His other friends are
so grateful to you.'
`I sew his ears on from time to time, sure'
Attachment (20_texinfo.diff): text/x-diff, 606 bytes
_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
by Werner Koch | 9 Aug 15:00 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-104-ge6d3548

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, master has been updated
       via  e6d354865bf8f3d4c1bb5e8157a76fdd442cff41 (commit)
      from  9933b9e5e1a3f5b1019c75f93bd265d4a1ecc270 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit e6d354865bf8f3d4c1bb5e8157a76fdd442cff41
Author: Werner Koch <wk <at> gnupg.org>
Date:   Sat Aug 9 14:36:59 2014 +0200

    tests: Add a benchmark for Elgamal.

    * tests/benchmark.c (sample_public_elg_key_1024): New.
    (sample_private_elg_key_1024): New.
    (sample_public_elg_key_2048, sample_private_elg_key_2048): New.
    (sample_public_elg_key_3072, sample_private_elg_key_3072): New.
    (elg_bench): New.
    (main): Add elg_bench.  Add commands "elg" and "public".

diff --git a/tests/benchmark.c b/tests/benchmark.c
index 042e721..2621551 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
 <at>  <at>  -250,6 +250,142  <at>  <at>  static const char sample_public_dsa_key_3072[] =
 "))\n";

 
+static const char sample_public_elg_key_1024[] =
+"(public-key"
+"  (elg"
+"   (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6"
+       "64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A"
+       "EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4"
+       "52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)"
+"   (g #06#)"
+"   (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C"
+       "80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7"
+       "3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85"
+       "D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)"
+"   ))";
+static const char sample_private_elg_key_1024[] =
+"(private-key"
+"  (elg"
+"   (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6"
+       "64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A"
+       "EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4"
+       "52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)"
+"   (g #06#)"
+"   (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C"
+       "80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7"
+       "3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85"
+       "D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)"
+"   (x #03656C6186FCD27D4A4B1F5010DC0D2AE7833B501E423FCD51DE5EB6D80DACFE#)"
+"   ))";
+
+
+static const char sample_public_elg_key_2048[] =
+"(public-key"
+"  (elg"
+"   (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6"
+       "38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D"
+       "C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97"
+       "73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0"
+       "EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5"
+       "5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8"
+       "D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135"
+       "768011AF6B622C5AF366EF0196FC4EAEAA8127#)"
+"   (g #07#)"
+"   (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8"
+       "D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210"
+       "2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354"
+       "D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E"
+       "5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F"
+       "6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8"
+       "2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237"
+       "D493E092AEA2371AA904009C8960B0969D12#)"
+"   ))";
+static const char sample_private_elg_key_2048[] =
+"(private-key"
+"  (elg"
+"   (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6"
+       "38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D"
+       "C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97"
+       "73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0"
+       "EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5"
+       "5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8"
+       "D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135"
+       "768011AF6B622C5AF366EF0196FC4EAEAA8127#)"
+"   (g #07#)"
+"   (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8"
+       "D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210"
+       "2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354"
+       "D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E"
+       "5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F"
+       "6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8"
+       "2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237"
+       "D493E092AEA2371AA904009C8960B0969D12#)"
+"   (x #0628C3903972C55BDC1BC4223075616D3F3BA57D55532DDB40CB14CF72070E0D28BF"
+       "D0402B9088D25ED8FC#)"
+"  ))";
+
+static const char sample_public_elg_key_3072[] =
+"(public-key"
+"  (elg"
+"   (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72"
+       "BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0"
+       "5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2"
+       "C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2"
+       "FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C"
+       "F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888"
+       "A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4"
+       "7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0"
+       "D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2"
+       "390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C"
+       "84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42"
+       "D226206FDF7D1FB93A5457#)"
+"   (g #0B#)"
+"   (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF"
+       "3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D"
+       "D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0"
+       "E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79"
+       "12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2"
+       "289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686"
+       "9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23"
+       "79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A"
+       "A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171"
+       "5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C"
+       "9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9"
+       "4DDDEFAFD2C7C66E235D#)"
+"   ))";
+static const char sample_private_elg_key_3072[] =
+"(private-key"
+"  (elg"
+"   (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72"
+       "BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0"
+       "5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2"
+       "C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2"
+       "FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C"
+       "F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888"
+       "A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4"
+       "7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0"
+       "D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2"
+       "390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C"
+       "84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42"
+       "D226206FDF7D1FB93A5457#)"
+"   (g #0B#)"
+"   (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF"
+       "3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D"
+       "D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0"
+       "E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79"
+       "12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2"
+       "289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686"
+       "9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23"
+       "79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A"
+       "A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171"
+       "5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C"
+       "9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9"
+       "4DDDEFAFD2C7C66E235D#)"
+"   (x #03A73F0389E470AAC831B039F8AA0C4EBD3A47DD083E32EEA08E4911236CD597C272"
+       "9823D47A51C8535DA52FE6DAB3E8D1C20D#)"
+"  ))";
+
+
 #define DIM(v)		     (sizeof(v)/sizeof((v)[0]))
 #define DIMof(type,member)   DIM(((type *)0)->member)
 #define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
 <at>  <at>  -877,7 +1013,7  <at>  <at>  rsa_bench (int iterations, int print_header, int no_blinding)
   int testno;

   if (print_header)
-    printf ("Algorithm         generate %4d*sign %4d*verify\n"
+    printf ("Algorithm         generate %4d*priv %4d*public\n"
             "------------------------------------------------\n",
             iterations, iterations );
   for (testno=0; testno < DIM (p_sizes); testno++)
 <at>  <at>  -989,6 +1125,115  <at>  <at>  rsa_bench (int iterations, int print_header, int no_blinding)
 }

 
+static void
+elg_bench (int iterations, int print_header)
+{
+  gpg_error_t err;
+  gcry_sexp_t pub_key[3], sec_key[3];
+  int p_sizes[3] = { 1024, 2048, 3072 };
+  gcry_sexp_t data = NULL;
+  gcry_sexp_t enc = NULL;
+  gcry_sexp_t plain = NULL;
+  int i, j;
+
+  err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_elg_key_1024,
+                         strlen (sample_public_elg_key_1024));
+  if (!err)
+    err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_elg_key_1024,
+                           strlen (sample_private_elg_key_1024));
+  if (!err)
+    err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_elg_key_2048,
+                           strlen (sample_public_elg_key_2048));
+  if (!err)
+    err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_elg_key_2048,
+                           strlen (sample_private_elg_key_2048));
+  if (!err)
+    err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_elg_key_3072,
+                           strlen (sample_public_elg_key_3072));
+  if (!err)
+    err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_elg_key_3072,
+                           strlen (sample_private_elg_key_3072));
+  if (err)
+    {
+      fprintf (stderr, PGM ": converting sample keys failed: %s\n",
+               gcry_strerror (err));
+      exit (1);
+    }
+
+  if (print_header)
+    printf ("Algorithm         generate %4d*priv %4d*public\n"
+            "------------------------------------------------\n",
+            iterations, iterations );
+  for (i=0; i < DIM (p_sizes); i++)
+    {
+      char timerbuf1[100];
+
+      {
+        gcry_mpi_t x = gcry_mpi_new (p_sizes[i]);
+        gcry_mpi_randomize (x, p_sizes[i] - 16, GCRY_WEAK_RANDOM);
+        err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
+        gcry_mpi_release (x);
+      }
+      if (err)
+        {
+          fprintf (stderr, PGM ": converting data failed: %s\n",
+                   gcry_strerror (err));
+          exit (1);
+        }
+
+      printf ("ELG %d bit             -", p_sizes[i]);
+      fflush (stdout);
+
+      start_timer ();
+      for (j=0; j < iterations; j++)
+        {
+          gcry_sexp_release (enc);
+          err = gcry_pk_encrypt (&enc, data, pub_key[i]);
+          if (err)
+            {
+              putchar ('\n');
+              fprintf (stderr, PGM ": encrypt failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
+        }
+      stop_timer ();
+      snprintf (timerbuf1, sizeof timerbuf1, "   %s", elapsed_time ());
+      fflush (stdout);
+
+      start_timer ();
+      for (j=0; j < iterations; j++)
+        {
+          gcry_sexp_release (plain);
+          err = gcry_pk_decrypt (&plain, enc, sec_key[i]);
+          if (err)
+            {
+              putchar ('\n');
+              fprintf (stderr, PGM ": decrypt failed: %s\n",
+                       gpg_strerror (err));
+              exit (1);
+            }
+        }
+      stop_timer ();
+
+      printf ("   %s  %s\n", elapsed_time (), timerbuf1);
+      fflush (stdout);
+
+      gcry_sexp_release (plain);
+      plain = NULL;
+      gcry_sexp_release (enc);
+      enc = NULL;
+      gcry_sexp_release (data);
+      data = NULL;
+    }
+
+  for (i=0; i < DIM (p_sizes); i++)
+    {
+      gcry_sexp_release (sec_key[i]);
+      gcry_sexp_release (pub_key[i]);
+    }
+}
+

 static void
 dsa_bench (int iterations, int print_header)
 <at>  <at>  -1026,7 +1271,7  <at>  <at>  dsa_bench (int iterations, int print_header)
     }

   if (print_header)
-    printf ("Algorithm         generate %4d*sign %4d*verify\n"
+    printf ("Algorithm         generate %4d*priv %4d*public\n"
             "------------------------------------------------\n",
             iterations, iterations );
   for (i=0; i < DIM (q_sizes); i++)
 <at>  <at>  -1104,7 +1349,7  <at>  <at>  ecc_bench (int iterations, int print_header)
   int testno;

   if (print_header)
-    printf ("Algorithm         generate %4d*sign %4d*verify\n"
+    printf ("Algorithm         generate %4d*priv %4d*public\n"
             "------------------------------------------------\n",
             iterations, iterations );
   for (testno=0; testno < DIM (p_sizes); testno++)
 <at>  <at>  -1511,6 +1756,7  <at>  <at>  main( int argc, char **argv )
       cipher_bench (NULL);
       putchar ('\n');
       rsa_bench (pk_count, 1, no_blinding);
+      elg_bench (pk_count, 0);
       dsa_bench (pk_count, 0);
       ecc_bench (pk_count, 0);
       putchar ('\n');
 <at>  <at>  -1559,11 +1805,24  <at>  <at>  main( int argc, char **argv )
     {
         mpi_bench ();
     }
+  else if ( !strcmp (*argv, "pubkey"))
+    {
+        gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        rsa_bench (pk_count, 1, no_blinding);
+        elg_bench (pk_count, 0);
+        dsa_bench (pk_count, 0);
+        ecc_bench (pk_count, 0);
+    }
   else if ( !strcmp (*argv, "rsa"))
     {
         gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
         rsa_bench (pk_count, 1, no_blinding);
     }
+  else if ( !strcmp (*argv, "elg"))
+    {
+        gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        elg_bench (pk_count, 1);
+    }
   else if ( !strcmp (*argv, "dsa"))
     {
         gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);

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

Summary of changes:
 tests/benchmark.c |  265 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 262 insertions(+), 3 deletions(-)

hooks/post-receive
--

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

_______________________________________________
Gnupg-commits mailing list
Gnupg-commits <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
Andreas Metzler | 9 Aug 11:32 2014
X-Face
Picon

Re: [Announce] [security fix] Libgcrypt and GnuPG

Werner Koch <wk <at> gnupg.org> wrote:
[...]
> While evaluating the "Get Your Hands Off My Laptop" [1] paper I missed
> to describe [2] a software combination which has not been fixed and is
> thus vulnerable to the attack described by the paper.  If you are using
[...]
>   gpg2 --version

> on the command line; the second line of the output gives the Libgcrypt
> version:

>   gpg (GnuPG) 2.0.25
>   libgcrypt 1.5.3

> In this example Libgcrypt is vulnerable.
[ and 1.5.4 is not ... ]

Hello,

libgcrypt 1.5.3 -> 1.5.4 seem to be essentiall 5 git commits. - Is
the bugfix in a single commit, and if it is which one?

thanks, cu Andreas
--

-- 
`What a good friend you are to him, Dr. Maturin. His other friends are
so grateful to you.'
`I sew his ears on from time to time, sure'
by NIIBE Yutaka | 8 Aug 02:44 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-103-g9933b9e

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, master has been updated
       via  9933b9e5e1a3f5b1019c75f93bd265d4a1ecc270 (commit)
      from  4ce77b0a810d3c889c07dfb385127d90fa1ae36a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9933b9e5e1a3f5b1019c75f93bd265d4a1ecc270
Author: NIIBE Yutaka <gniibe <at> fsij.org>
Date:   Fri Aug 8 09:35:31 2014 +0900

    ecc: Add cofactor to domain parameters.

    * src/ec-context.h (mpi_ec_ctx_s): Add cofactor 'h'.
    * cipher/ecc-common.h (elliptic_curve_t): Add cofactor 'h'.
    (_gcry_ecc_update_curve_param): New API adding cofactor.

    * cipher/ecc-curves.c (ecc_domain_parms_t): Add cofactor 'h'.
    (ecc_domain_parms_t domain_parms): Add cofactors.
    (_gcry_ecc_fill_in_curve, _gcry_ecc_update_curve_param)
    (_gcry_ecc_get_curve, _gcry_mpi_ec_new, _gcry_ecc_get_param_sexp)
    (_gcry_ecc_get_mpi): Handle cofactor.
    * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Likewise.
    * cipher/ecc-misc.c (_gcry_ecc_curve_free)
    (_gcry_ecc_curve_copy): Likewise.
    * cipher/ecc.c (nist_generate_key, ecc_generate)
    (ecc_check_secret_key, ecc_sign, ecc_verify, ecc_encrypt_raw)
    (ecc_decrypt_raw, _gcry_pk_ecc_get_sexp, _gcry_pubkey_spec_ecc):
    Likewise.
    (compute_keygrip): Handle cofactor, but skip it for its computation.
    * mpi/ec.c (ec_deinit): Likewise.
    * tests/t-mpi-point.c (context_param): Likewise.
    (test_curve): Add cofactors.
    * tests/curves.c (sample_key_1, sample_key_2): Add cofactors.
    * tests/keygrip.c (key_grips): Add cofactors.
    --

    We keep compatibility of compute_keygrip in cipher/ecc.c.

diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index f066b4b..83bf20d 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
 <at>  <at>  -32,6 +32,7  <at>  <at>  typedef struct
                            or d as used by Twisted Edwards curves.  */
   mpi_point_struct G;   /* Base point (generator).  */
   gcry_mpi_t n;         /* Order of G.  */
+  gcry_mpi_t h;         /* Cofactor.  */
   const char *name;     /* Name of the curve or NULL.  */
 } elliptic_curve_t;

 <at>  <at>  -75,7 +76,7  <at>  <at>  gpg_err_code_t _gcry_ecc_update_curve_param (const char *name,
                                              enum ecc_dialects *dialect,
                                              gcry_mpi_t *p, gcry_mpi_t *a,
                                              gcry_mpi_t *b, gcry_mpi_t *g,
-                                             gcry_mpi_t *n);
+                                             gcry_mpi_t *n, gcry_mpi_t *h);

 const char *_gcry_ecc_get_curve (gcry_sexp_t keyparms,
                                  int iterator,
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index cd85361..fd47c1d 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
 <at>  <at>  -110,6 +110,7  <at>  <at>  typedef struct
                                  Curves b is used for d.  */
   const char *n;              /* The order of the base point.  */
   const char *g_x, *g_y;      /* Base point.  */
+  const char *h;              /* Cofactor.  */
 } ecc_domain_parms_t;

 
 <at>  <at>  -125,7 +126,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
-      "0x6666666666666666666666666666666666666666666666666666666666666658"
+      "0x6666666666666666666666666666666666666666666666666666666666666658",
+      "0x08"
     },
 #if 0 /* No real specs yet found.  */
     {
 <at>  <at>  -140,7 +142,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "706022B36F1C0338AD63CF181B0E71A5E106AF79",
       "0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
       "6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
-      "0x22"
+      "0x22",
+      "0x08"
     },
 #endif /*0*/
     {
 <at>  <at>  -152,7 +155,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",

       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
-      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
+      "0x01"
     },
     {
       "NIST P-224", 224, 1,
 <at>  <at>  -163,7 +167,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,

       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
+      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+      "0x01"
     },
     {
       "NIST P-256", 256, 1,
 <at>  <at>  -174,7 +179,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",

       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
-      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+      "0x01"
     },
     {
       "NIST P-384", 384, 1,
 <at>  <at>  -191,7 +197,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
       "5502f25dbf55296c3a545e3872760ab7",
       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
-      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
+      "0a60b1ce1d7e819d7a431d7c90ea0e5f",
+      "0x01"
     },
     {
       "NIST P-521", 521, 1,
 <at>  <at>  -208,7 +215,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
       "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
       "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
-      "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+      "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
+      "0x01"
     },

     { "brainpoolP160r1", 160, 0,
 <at>  <at>  -218,7 +226,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
-      "0x1667cb477a1a8ec338f94741669c976316da6321"
+      "0x1667cb477a1a8ec338f94741669c976316da6321",
+      "0x01"
     },

     { "brainpoolP192r1", 192, 0,
 <at>  <at>  -228,7 +237,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
-      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
+      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
+      "0x01"
     },

     { "brainpoolP224r1", 224, 0,
 <at>  <at>  -238,7 +248,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
-      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
+      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
+      "0x01"
     },

     { "brainpoolP256r1", 256, 0,
 <at>  <at>  -248,7 +259,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
-      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
+      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
+      "0x01"
     },

     { "brainpoolP320r1", 320, 0,
 <at>  <at>  -264,7 +276,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
       "10af8d0d39e20611",
       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
-      "d35245d1692e8ee1"
+      "d35245d1692e8ee1",
+      "0x01"
     },

     { "brainpoolP384r1", 384, 0,
 <at>  <at>  -280,7 +293,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
       "e826e03436d646aaef87b2e247d4af1e",
       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
-      "0e4646217791811142820341263c5315"
+      "0e4646217791811142820341263c5315",
+      "0x01"
     },

     { "brainpoolP512r1", 512, 0,
 <at>  <at>  -296,7 +310,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
-      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
+      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
+      "0x01"
     },
     {
       "GOST2001-test", 256, 0,
 <at>  <at>  -308,6 +323,7  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =

       "0x0000000000000000000000000000000000000000000000000000000000000002",
       "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-A", 256, 0,
 <at>  <at>  -317,7 +333,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x00000000000000000000000000000000000000000000000000000000000000a6",
       "0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
-      "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14"
+      "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-B", 256, 0,
 <at>  <at>  -327,7 +344,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x3e1af419a269a5f866a7d3c25c3df80ae979259373ff2b182f49d4ce7e1bbc8b",
       "0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
-      "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc"
+      "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-C", 256, 0,
 <at>  <at>  -337,7 +355,8  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x000000000000000000000000000000000000000000000000000000000000805a",
       "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
       "0x0000000000000000000000000000000000000000000000000000000000000000",
-      "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67"
+      "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
+      "0x01"
     },
     {
       "GOST2012-test", 511, 0,
 <at>  <at>  -354,6 +373,7  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
       "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
       "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
+      "0x01"
     },
     {
       "GOST2012-tc26-A", 512, 0,
 <at>  <at>  -370,6 +390,7  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000003",
       "0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
         "df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
+      "0x01"
     },
     {
       "GOST2012-tc26-B", 512, 0,
 <at>  <at>  -386,6 +407,7  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000002",
       "0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
         "dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
+      "0x01"
     },

     {
 <at>  <at>  -396,10 +418,11  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x0000000000000000000000000000000000000000000000000000000000000007",
       "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
       "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
-      "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
+      "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+      "0x01"
     },

-    { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
+    { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
   };

 
 <at>  <at>  -530,6 +553,8  <at>  <at>  _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
         curve->b = scanval (domain_parms[idx].b);
       if (!curve->n)
         curve->n = scanval (domain_parms[idx].n);
+      if (!curve->h)
+        curve->h = scanval (domain_parms[idx].h);
       if (!curve->G.x)
         curve->G.x = scanval (domain_parms[idx].g_x);
       if (!curve->G.y)
 <at>  <at>  -545,7 +570,7  <at>  <at>  _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,

 
 /* Give the name of the curve NAME, store the curve parameters into P,
-   A, B, G, and N if they point to NULL value.  Note that G is returned
+   A, B, G, N, and H if they point to NULL value.  Note that G is returned
    in standard uncompressed format.  Also update MODEL and DIALECT if
    they are not NULL. */
 gpg_err_code_t
 <at>  <at>  -553,7 +578,7  <at>  <at>  _gcry_ecc_update_curve_param (const char *name,
                               enum gcry_mpi_ec_models *model,
                               enum ecc_dialects *dialect,
                               gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
-                              gcry_mpi_t *g, gcry_mpi_t *n)
+                              gcry_mpi_t *g, gcry_mpi_t *n, gcry_mpi_t *h)
 {
   int idx;

 <at>  <at>  -603,6 +628,11  <at>  <at>  _gcry_ecc_update_curve_param (const char *name,
       _gcry_mpi_release (*n);
       *n = scanval (domain_parms[idx].n);
     }
+  if (h)
+    {
+      _gcry_mpi_release (*h);
+      *h = scanval (domain_parms[idx].h);
+    }
   return 0;
 }

 <at>  <at>  -640,8 +670,8  <at>  <at>  _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
   /*
    * Extract the curve parameters..
    */
-  rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgn",
-                                         &E.p, &E.a, &E.b, &mpi_g, &E.n,
+  rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgnh",
+                                         &E.p, &E.a, &E.b, &mpi_g, &E.n, &E.h,
                                          NULL));
   if (rc == GPG_ERR_NO_OBJ)
     {
 <at>  <at>  -699,17 +729,22  <at>  <at>  _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
                   if (!mpi_cmp (tmp, E.n))
                     {
                       mpi_free (tmp);
-                      tmp = scanval (domain_parms[idx].g_x);
-                      if (!mpi_cmp (tmp, E.G.x))
+                      tmp = scanval (domain_parms[idx].h);
+                      if (!mpi_cmp (tmp, E.h))
                         {
                           mpi_free (tmp);
-                          tmp = scanval (domain_parms[idx].g_y);
-                          if (!mpi_cmp (tmp, E.G.y))
+                          tmp = scanval (domain_parms[idx].g_x);
+                          if (!mpi_cmp (tmp, E.G.x))
                             {
-                              result = domain_parms[idx].desc;
-                              if (r_nbits)
-                                *r_nbits = domain_parms[idx].nbits;
-                              goto leave;
+                              mpi_free (tmp);
+                              tmp = scanval (domain_parms[idx].g_y);
+                              if (!mpi_cmp (tmp, E.G.y))
+                                {
+                                  result = domain_parms[idx].desc;
+                                  if (r_nbits)
+                                    *r_nbits = domain_parms[idx].nbits;
+                                  goto leave;
+                                }
                             }
                         }
                     }
 <at>  <at>  -726,6 +761,7  <at>  <at>  _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
   _gcry_mpi_release (mpi_g);
   _gcry_mpi_point_free_parts (&E.G);
   _gcry_mpi_release (E.n);
+  _gcry_mpi_release (E.h);
   return result;
 }

 <at>  <at>  -857,6 +893,7  <at>  <at>  _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
   gcry_mpi_t b = NULL;
   gcry_mpi_point_t G = NULL;
   gcry_mpi_t n = NULL;
+  gcry_mpi_t h = NULL;
   gcry_mpi_point_t Q = NULL;
   gcry_mpi_t d = NULL;
   int flags = 0;
 <at>  <at>  -899,6 +936,9  <at>  <at>  _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
           errc = mpi_from_keyparam (&n, keyparam, "n");
           if (errc)
             goto leave;
+          errc = mpi_from_keyparam (&h, keyparam, "h");
+          if (errc)
+            goto leave;
         }
     }
   else
 <at>  <at>  -972,6 +1012,11  <at>  <at>  _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
           n = E->n;
           E->n = NULL;
         }
+      if (!h)
+        {
+          h = E->h;
+          E->h = NULL;
+        }
       _gcry_ecc_curve_free (E);
       xfree (E);
     }
 <at>  <at>  -998,6 +1043,11  <at>  <at>  _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
           ec->n = n;
           n = NULL;
         }
+      if (h)
+        {
+          ec->h = h;
+          h = NULL;
+        }

       /* Now that we know the curve name we can look for the public key
          Q.  point_from_keyparam needs to know the curve parameters so
 <at>  <at>  -1036,6 +1086,7  <at>  <at>  _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
   mpi_free (b);
   _gcry_mpi_point_release (G);
   mpi_free (n);
+  mpi_free (h);
   _gcry_mpi_point_release (Q);
   mpi_free (d);
   return errc;
 <at>  <at>  -1050,7 +1101,7  <at>  <at>  _gcry_ecc_get_param_sexp (const char *name)
   elliptic_curve_t E;
   mpi_ec_t ctx;
   gcry_mpi_t g_x, g_y;
-  gcry_mpi_t pkey[6];
+  gcry_mpi_t pkey[7];
   gcry_sexp_t result;
   int i;

 <at>  <at>  -1074,14 +1125,15  <at>  <at>  _gcry_ecc_get_param_sexp (const char *name)
   pkey[2] = E.b;
   pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
   pkey[4] = E.n;
-  pkey[5] = NULL;
+  pkey[5] = E.h;
+  pkey[6] = NULL;

   mpi_free (g_x);
   mpi_free (g_y);

   if (sexp_build (&result, NULL,
-                  "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
-                  pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]))
+                  "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)))",
+                  pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]))
     result = NULL;

   for (i=0; pkey[i]; i++)
 <at>  <at>  -1108,6 +1160,8  <at>  <at>  _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
     return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
   if (!strcmp (name, "n") && ec->n)
     return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
+  if (!strcmp (name, "h") && ec->h)
+    return mpi_is_const (ec->h) && !copy? ec->h : mpi_copy (ec->h);
   if (!strcmp (name, "d") && ec->d)
     return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);

 <at>  <at>  -1206,6 +1260,11  <at>  <at>  _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
       mpi_free (ec->n);
       ec->n = mpi_copy (newvalue);
     }
+  else if (!strcmp (name, "h"))
+    {
+      mpi_free (ec->h);
+      ec->h = mpi_copy (newvalue);
+    }
   else if (*name == 'q' && (!name[1] || name[1] == ' <at> '))
     {
       if (newvalue)
diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 65024a3..a12ebab 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
 <at>  <at>  -525,6 +525,7  <at>  <at>  _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&sk->E.G);
   point_set (&sk->E.G, &E->G);
   sk->E.n = mpi_copy (E->n);
+  sk->E.h = mpi_copy (E->h);
   point_init (&sk->Q);
   point_set (&sk->Q, &Q);

diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 3f284fe..88266b5 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
 <at>  <at>  -43,6 +43,7  <at>  <at>  _gcry_ecc_curve_free (elliptic_curve_t *E)
   mpi_free (E->b);  E->b = NULL;
   _gcry_mpi_point_free_parts (&E->G);
   mpi_free (E->n);  E->n = NULL;
+  mpi_free (E->h);  E->h = NULL;
 }

 
 <at>  <at>  -63,6 +64,7  <at>  <at>  _gcry_ecc_curve_copy (elliptic_curve_t E)
   _gcry_mpi_point_init (&R.G);
   point_set (&R.G, &E.G);
   R.n = mpi_copy (E.n);
+  R.h = mpi_copy (E.h);

   return R;
 }
diff --git a/cipher/ecc.c b/cipher/ecc.c
index a27d2c6..8bdbd56 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
 <at>  <at>  -142,6 +142,7  <at>  <at>  nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&sk->E.G);
   point_set (&sk->E.G, &E->G);
   sk->E.n = mpi_copy (E->n);
+  sk->E.h = mpi_copy (E->h);
   point_init (&sk->Q);

   /* We want the Q=(x,y) be a "compliant key" in terms of the
 <at>  <at>  -456,6 +457,7  <at>  <at>  ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
       log_printmpi ("ecgen curve   a", E.a);
       log_printmpi ("ecgen curve   b", E.b);
       log_printmpi ("ecgen curve   n", E.n);
+      log_printmpi ("ecgen curve   h", E.h);
       log_printpnt ("ecgen curve G", &E.G, NULL);
     }

 <at>  <at>  -524,14 +526,14  <at>  <at>  ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
     rc = sexp_build (r_skey, NULL,
                      "(key-data"
                      " (public-key"
-                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))"
+                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))"
                      " (private-key"
-                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))"
+                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))"
                      " )",
                      curve_info, curve_flags,
-                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public,
+                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
                      curve_info, curve_flags,
-                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret);
+                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public, secret);
   else
     rc = sexp_build (r_skey, NULL,
                      "(key-data"
 <at>  <at>  -554,6 +556,7  <at>  <at>  ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
       log_printmpi ("ecgen result  b", sk.E.b);
       log_printmpi ("ecgen result  G", base);
       log_printmpi ("ecgen result  n", sk.E.n);
+      log_printmpi ("ecgen result  h", sk.E.h);
       log_printmpi ("ecgen result  Q", public);
       log_printmpi ("ecgen result  d", secret);
       if ((flags & PUBKEY_FLAG_EDDSA))
 <at>  <at>  -604,9 +607,9  <at>  <at>  ecc_check_secret_key (gcry_sexp_t keyparms)

   /* Extract the parameters.  */
   if ((flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d",
+    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
                              &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                             &mpi_q, &sk.d, NULL);
+                             &sk.E.h, &mpi_q, &sk.d, NULL);
   else
     rc = sexp_extract_param (keyparms, NULL, "/q?+d",
                              &mpi_q, &sk.d, NULL);
 <at>  <at>  -624,7 +627,7  <at>  <at>  ecc_check_secret_key (gcry_sexp_t keyparms)
           rc = _gcry_ecc_update_curve_param (curvename,
                                              &sk.E.model, &sk.E.dialect,
                                              &sk.E.p, &sk.E.a, &sk.E.b,
-                                             &mpi_g, &sk.E.n);
+                                             &mpi_g, &sk.E.n, &sk.E.h);
           if (rc)
             return rc;
         }
 <at>  <at>  -660,11 +663,12  <at>  <at>  ecc_check_secret_key (gcry_sexp_t keyparms)
       log_printmpi ("ecc_testkey   b", sk.E.b);
       log_printpnt ("ecc_testkey g",   &sk.E.G, NULL);
       log_printmpi ("ecc_testkey   n", sk.E.n);
+      log_printmpi ("ecc_testkey   h", sk.E.h);
       log_printmpi ("ecc_testkey   q", mpi_q);
       if (!fips_mode ())
         log_printmpi ("ecc_testkey   d", sk.d);
     }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
 <at>  <at>  -701,6 +705,7  <at>  <at>  ecc_check_secret_key (gcry_sexp_t keyparms)
   _gcry_mpi_release (mpi_g);
   point_free (&sk.E.G);
   _gcry_mpi_release (sk.E.n);
+  _gcry_mpi_release (sk.E.h);
   _gcry_mpi_release (mpi_q);
   point_free (&sk.Q);
   _gcry_mpi_release (sk.d);
 <at>  <at>  -741,9 +746,9  <at>  <at>  ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
    * Extract the key.
    */
   if ((ctx.flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d",
+    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
                              &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                             &mpi_q, &sk.d, NULL);
+                             &sk.E.h, &mpi_q, &sk.d, NULL);
   else
     rc = sexp_extract_param (keyparms, NULL, "/q?+d",
                              &mpi_q, &sk.d, NULL);
 <at>  <at>  -793,11 +798,12  <at>  <at>  ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       log_printmpi ("ecc_sign      b", sk.E.b);
       log_printpnt ("ecc_sign    g",   &sk.E.G, NULL);
       log_printmpi ("ecc_sign      n", sk.E.n);
+      log_printmpi ("ecc_sign      h", sk.E.h);
       log_printmpi ("ecc_sign      q", mpi_q);
       if (!fips_mode ())
         log_printmpi ("ecc_sign      d", sk.d);
     }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
 <at>  <at>  -838,6 +844,7  <at>  <at>  ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_mpi_release (mpi_g);
   point_free (&sk.E.G);
   _gcry_mpi_release (sk.E.n);
+  _gcry_mpi_release (sk.E.h);
   _gcry_mpi_release (mpi_q);
   point_free (&sk.Q);
   _gcry_mpi_release (sk.d);
 <at>  <at>  -905,9 +912,9  <at>  <at>  ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
    * Extract the key.
    */
   if ((ctx.flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q",
+    rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?h?/q",
                              &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
-                             &mpi_q, NULL);
+                             &pk.E.n, &mpi_q, NULL);
   else
     rc = sexp_extract_param (s_keyparms, NULL, "/q",
                              &mpi_q, NULL);
 <at>  <at>  -958,9 +965,10  <at>  <at>  ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
       log_printmpi ("ecc_verify    b", pk.E.b);
       log_printpnt ("ecc_verify  g",   &pk.E.G, NULL);
       log_printmpi ("ecc_verify    n", pk.E.n);
+      log_printmpi ("ecc_verify    h", pk.E.h);
       log_printmpi ("ecc_verify    q", mpi_q);
     }
-  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !mpi_q)
+  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
 <at>  <at>  -1036,6 +1044,7  <at>  <at>  ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   _gcry_mpi_release (mpi_g);
   point_free (&pk.E.G);
   _gcry_mpi_release (pk.E.n);
+  _gcry_mpi_release (pk.E.h);
   _gcry_mpi_release (mpi_q);
   point_free (&pk.Q);
   _gcry_mpi_release (data);
 <at>  <at>  -1115,8 +1124,8  <at>  <at>  ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /*
    * Extract the key.
    */
-  rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?+q",
-                           &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
+  rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?+q",
+                           &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, &pk.E.h,
                            &mpi_q, NULL);
   if (rc)
     goto leave;
 <at>  <at>  -1159,9 +1168,10  <at>  <at>  ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       log_printmpi ("ecc_encrypt    b", pk.E.b);
       log_printpnt ("ecc_encrypt  g",   &pk.E.G, NULL);
       log_printmpi ("ecc_encrypt    n", pk.E.n);
+      log_printmpi ("ecc_encrypt    h", pk.E.h);
       log_printmpi ("ecc_encrypt    q", mpi_q);
     }
-  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !mpi_q)
+  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
 <at>  <at>  -1219,6 +1229,7  <at>  <at>  ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_mpi_release (mpi_g);
   point_free (&pk.E.G);
   _gcry_mpi_release (pk.E.n);
+  _gcry_mpi_release (pk.E.h);
   _gcry_mpi_release (mpi_q);
   point_free (&pk.Q);
   _gcry_mpi_release (data);
 <at>  <at>  -1282,9 +1293,9  <at>  <at>  ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /*
    * Extract the key.
    */
-  rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?+d",
+  rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?+d",
                            &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                           &sk.d, NULL);
+                           &sk.E.h, &sk.d, NULL);
   if (rc)
     goto leave;
   if (mpi_g)
 <at>  <at>  -1325,10 +1336,11  <at>  <at>  ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       log_printmpi ("ecc_decrypt    b", sk.E.b);
       log_printpnt ("ecc_decrypt  g",   &sk.E.G, NULL);
       log_printmpi ("ecc_decrypt    n", sk.E.n);
+      log_printmpi ("ecc_decrypt    h", sk.E.h);
       if (!fips_mode ())
         log_printmpi ("ecc_decrypt    d", sk.d);
     }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
 <at>  <at>  -1385,6 +1397,7  <at>  <at>  ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_mpi_release (mpi_g);
   point_free (&sk.E.G);
   _gcry_mpi_release (sk.E.n);
+  _gcry_mpi_release (sk.E.h);
   _gcry_mpi_release (sk.d);
   _gcry_mpi_release (data_e);
   xfree (curvename);
 <at>  <at>  -1454,8 +1467,8  <at>  <at>  ecc_get_nbits (gcry_sexp_t parms)
 static gpg_err_code_t
 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
 {
-#define N_COMPONENTS 6
-  static const char names[N_COMPONENTS+1] = "pabgnq";
+#define N_COMPONENTS 7
+  static const char names[N_COMPONENTS] = "pabgnhq";
   gpg_err_code_t rc;
   gcry_sexp_t l1;
   gcry_mpi_t values[N_COMPONENTS];
 <at>  <at>  -1483,24 +1496,24  <at>  <at>  compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
   if ((flags & PUBKEY_FLAG_PARAM))
     {
       if ((flags & PUBKEY_FLAG_EDDSA))
-        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?/q",
+        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?/q",
                                  &values[0], &values[1], &values[2],
                                  &values[3], &values[4], &values[5],
-                                 NULL);
+                                 &values[6], NULL);
       else
-        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?q",
+        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?q",
                                  &values[0], &values[1], &values[2],
                                  &values[3], &values[4], &values[5],
-                                 NULL);
+                                 &values[6], NULL);
     }
   else
     {
       if ((flags & PUBKEY_FLAG_EDDSA))
         rc = sexp_extract_param (keyparms, NULL, "/q",
-                                 &values[5], NULL);
+                                 &values[6], NULL);
       else
         rc = sexp_extract_param (keyparms, NULL, "q",
-                                 &values[5], NULL);
+                                 &values[6], NULL);
     }
   if (rc)
     goto leave;
 <at>  <at>  -1517,7 +1530,7  <at>  <at>  compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
           rc = _gcry_ecc_update_curve_param (curvename,
                                              &model, &dialect,
                                              &values[0], &values[1], &values[2],
-                                             &values[3], &values[4]);
+                                             &values[3], &values[4], &values[5]);
           if (rc)
             goto leave;
         }
 <at>  <at>  -1555,7 +1568,7  <at>  <at>  compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
   if ((flags & PUBKEY_FLAG_EDDSA))
     {
       if (dialect == ECC_DIALECT_ED25519)
-        rc = _gcry_ecc_eddsa_ensure_compact (values[5], 256);
+        rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
       else
         rc = GPG_ERR_NOT_IMPLEMENTED;
       if (rc)
 <at>  <at>  -1567,6 +1580,9  <at>  <at>  compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
     {
       char buf[30];

+      if (idx == 5)
+	continue;		/* Skip cofactor. */
+
       if (mpi_is_opaque (values[idx]))
         {
           const unsigned char *raw;
 <at>  <at>  -1624,7 +1640,7  <at>  <at>  _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
   gcry_mpi_t mpi_G = NULL;
   gcry_mpi_t mpi_Q = NULL;

-  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->h)
     return GPG_ERR_BAD_CRYPT_CTX;

   if (mode == GCRY_PK_GET_SECKEY && !ec->d)
 <at>  <at>  -1676,15 +1692,15  <at>  <at>  _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
     {
       /* Let's return a private key. */
       rc = sexp_build (r_sexp, NULL,
-                       "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))",
-                       ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q, ec->d);
+                       "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))",
+                       ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q, ec->d);
     }
   else if (ec->Q)
     {
       /* Let's return a public key.  */
       rc = sexp_build (r_sexp, NULL,
-                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
-                       ec->p, ec->a, ec->b, mpi_G, ec->n, mpi_Q);
+                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))",
+                       ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q);
     }
   else
     rc = GPG_ERR_BAD_CRYPT_CTX;
 <at>  <at>  -1744,7 +1760,7  <at>  <at>  gcry_pk_spec_t _gcry_pubkey_spec_ecc =
     GCRY_PK_ECC, { 0, 0 },
     (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
     "ECC", ecc_names,
-    "pabgnq", "pabgnqd", "sw", "rs", "pabgnq",
+    "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq",
     ecc_generate,
     ecc_check_secret_key,
     ecc_encrypt_raw,
diff --git a/mpi/ec.c b/mpi/ec.c
index 4f35de0..737f12c 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -429,6 +429,7  <at>  <at>  ec_deinit (void *opaque)
   mpi_free (ctx->b);
   _gcry_mpi_point_release (ctx->G);
   mpi_free (ctx->n);
+  mpi_free (ctx->h);

   /* The key.  */
   _gcry_mpi_point_release (ctx->Q);
diff --git a/src/ec-context.h b/src/ec-context.h
index 60ca759..c8f2ad0 100644
--- a/src/ec-context.h
+++ b/src/ec-context.h
 <at>  <at>  -38,6 +38,7  <at>  <at>  struct mpi_ec_ctx_s
   gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
   gcry_mpi_point_t G;   /* Base point (generator).  */
   gcry_mpi_t n;         /* Order of G.  */
+  gcry_mpi_t h;         /* Cofactor.  */

   /* The actual key.  May not be set.  */
   gcry_mpi_point_t Q;   /* Public key.   */
diff --git a/tests/curves.c b/tests/curves.c
index 0581452..178a192 100644
--- a/tests/curves.c
+++ b/tests/curves.c
 <at>  <at>  -41,6 +41,7  <at>  <at>  static char const sample_key_1[] =
 "  (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
         "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)\n"
 "  (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)\n"
+"  (h #000000000000000000000000000000000000000000000000000000000000000001#)\n"
 "  (q #0442B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146EE"
       "86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E#)\n"
 "  ))";
 <at>  <at>  -57,6 +58,7  <at>  <at>  static char const sample_key_2[] =
 "  (g #04bed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3"
         "1667cb477a1a8ec338f94741669c976316da6321#)\n"
 "  (n #00e95e4a5f737059dc60df5991d45029409e60fc09#)\n"
+"  (h #000000000000000000000000000000000000000000000000000000000000000001#)\n"
 "  (q #041111111111111111111111111111111111111111"
         "2222222222222222222222222222222222222222#)\n"
 "  ))";
diff --git a/tests/keygrip.c b/tests/keygrip.c
index 72960ea..3ef1de1 100644
--- a/tests/keygrip.c
+++ b/tests/keygrip.c
 <at>  <at>  -110,6 +110,7  <at>  <at>  static struct
       " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)"
       " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)"
       " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)"
+      " (h #000000000000000000000000000000000000000000000000000000000000000001#)"
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
       "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
     },
 <at>  <at>  -122,6 +123,7  <at>  <at>  static struct
       " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)"
       " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)"
       " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)"
+      " (h #000000000000000000000000000000000000000000000000000000000000000001#)"
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
       "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
     },
 <at>  <at>  -134,6 +136,7  <at>  <at>  static struct
       " (b #5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B#)"
       " (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)"
       " (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)"
+      " (h #000000000000000000000000000000000000000000000000000000000000000001#)"
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
       "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
     },
diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c
index 88bb5bd..d72cd27 100644
--- a/tests/t-mpi-point.c
+++ b/tests/t-mpi-point.c
 <at>  <at>  -57,6 +57,7  <at>  <at>  static struct
   const char *a, *b;          /* The coefficients. */
   const char *n;              /* The order of the base point.  */
   const char *g_x, *g_y;      /* Base point.  */
+  const char *h;              /* Cofactor.  */
 } test_curve[] =
   {
     {
 <at>  <at>  -67,7 +68,8  <at>  <at>  static struct
       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",

       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
-      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
+      "0x01"
     },
     {
       "NIST P-224",
 <at>  <at>  -77,7 +79,8  <at>  <at>  static struct
       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,

       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
+      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+      "0x01"
     },
     {
       "NIST P-256",
 <at>  <at>  -87,7 +90,8  <at>  <at>  static struct
       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",

       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
-      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+      "0x01"
     },
     {
       "NIST P-384",
 <at>  <at>  -103,7 +107,8  <at>  <at>  static struct
       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
       "5502f25dbf55296c3a545e3872760ab7",
       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
-      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
+      "0a60b1ce1d7e819d7a431d7c90ea0e5f",
+      "0x01"
     },
     {
       "NIST P-521",
 <at>  <at>  -119,7 +124,8  <at>  <at>  static struct
       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
-      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
+      "0x01"
     },
     {
       "Ed25519",
 <at>  <at>  -128,9 +134,10  <at>  <at>  static struct
       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
-      "0x6666666666666666666666666666666666666666666666666666666666666658"
+      "0x6666666666666666666666666666666666666666666666666666666666666658",
+      "0x08"
     },
-    { NULL, NULL, NULL, NULL, NULL }
+    { NULL, NULL, NULL, NULL, NULL, NULL }
   };

 /* A sample public key for NIST P-256.  */
 <at>  <at>  -556,6 +563,8  <at>  <at>  context_param (void)
       if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
                              test_curve[idx].desc, ctx))
         continue;
+      if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
+        continue;

     }

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

Summary of changes:
 cipher/ecc-common.h |    3 +-
 cipher/ecc-curves.c |  129 +++++++++++++++++++++++++++++++++++++--------------
 cipher/ecc-eddsa.c  |    1 +
 cipher/ecc-misc.c   |    2 +
 cipher/ecc.c        |   88 +++++++++++++++++++++--------------
 mpi/ec.c            |    1 +
 src/ec-context.h    |    1 +
 tests/curves.c      |    2 +
 tests/keygrip.c     |    3 ++
 tests/t-mpi-point.c |   23 ++++++---
 10 files changed, 174 insertions(+), 79 deletions(-)

hooks/post-receive
--

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

_______________________________________________
Gnupg-commits mailing list
Gnupg-commits <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
NIIBE Yutaka | 8 Aug 04:22 2014

[PATCH] ecc: support Montgomery curve for gcry_mpi_ec_add_points

Here is a patch to support Montgomery curve for gcry_mpi_ec_mul_point.

Only x-coordinate is valid for this curve.

OK to commit?

diff --git a/mpi/ec.c b/mpi/ec.c
index 737f12c..2dc97aa 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -601,10 +601,17  <at>  <at>  _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");
+        if (x)
+          mpi_set (x, point->x);
+
+        if (y)
+          {
+            log_fatal ("%s: Getting Y-coordinate on %s is not supported\n",
+                       "_gcry_mpi_ec_get_affine", "Montgomery");
+            return -1;
+          }
       }
-      return -1;
+      return 0;

     case MPI_EC_EDWARDS:
       {
 <at>  <at>  -1074,6 +1081,35  <at>  <at>  add_points_edwards (mpi_point_t result,
 }

+/* Compute a step of Montgomery Ladder (only use X and Z in the point).
+   Inputs:  P1, P2, and x-coordinate of DIF = P1 - P1.
+   Outputs: PRD = 2 * P1 and  SUM = P1 + P2. */
+static void
+montgomery_ladder (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,
 <at>  <at>  -1145,6 +1181,72  <at>  <at>  _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_;
+      unsigned long sw;
+
+      /* Compute scalar point multiplication with Montgomery Ladder.
+         Note that we don't use Y-coordinate in the points at all.
+         RESULT->Y will be filled by zero.  */
+
+      nbits = mpi_get_nbits (scalar);
+      point_init (&p1);
+      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--)
+        {
+          sw = mpi_test_bit (scalar, j);
+          mpi_swap_cond (p1.x, p2.x, sw);
+          mpi_swap_cond (p1.z, p2.z, sw);
+          montgomery_ladder (&p1_, &p2_, &p1, &p2, point->x, ctx);
+          mpi_swap_cond (p1_.x, p2_.x, sw);
+          mpi_swap_cond (p1_.z, p2_.z, sw);
+
+          if (--j < 0)
+            break;
+
+          sw = mpi_test_bit (scalar, j);
+          mpi_swap_cond (p1_.x, p2_.x, sw);
+          mpi_swap_cond (p1_.z, p2_.z, sw);
+          montgomery_ladder (&p1, &p2, &p1_, &p2_, point->x, ctx);
+          mpi_swap_cond (p1.x, p2.x, sw);
+          mpi_swap_cond (p1.z, p2.z, sw);
+        }
+
+      z1 = mpi_new (0);
+      mpi_clear (result->y);
+      sw = (nbits & 1);
+      mpi_swap_cond (p1.x, p1_.x, sw);
+      mpi_swap_cond (p1.z, p1_.z, sw);
+
+      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);
+      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);
--

-- 
Werner Koch | 7 Aug 20:48 2014
Picon

Libgcrypt 1.5.4 released

Hello!

The GNU project is pleased to announce an update of the Libgcrypt 1.5
series: version 1.5.4.  This is a maintenance release with backports of
fixes from the current stable 1.6 series.

In general it is preferable to use the latest stable version.  However,
the 1.6 series introduced an ABI break and thus some older software may
not build or work correctly with 1.6.

Libgcrypt is a general purpose library of cryptographic building blocks.
It does not provide any implementation of OpenPGP or other protocols.
Thorough understanding of applied cryptography is required for proper
use Libgcrypt.

Noteworthy changes in version 1.5.4 (2014-08-07)
================================================

 * Declare 2016-12-31 as end-of-life for 1.5.

 Backported from 1.6:

 * Improved performance of RSA, DSA, and Elgamal by using a new
   exponentiation algorithm.

 * Fixed a subtle bug in mpi_set_bit which could set spurious bits.

 * Fixed a bug in an internal division function.

Download
========

Source code is hosted at the GnuPG FTP server and its mirrors as listed
at http://www.gnupg.org/download/mirrors.html .  On the primary server
the source tarball and its digital signature are:

 ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.5.4.tar.bz2 (1478k)
 ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.5.4.tar.bz2.sig

That file is bzip2 compressed.  A gzip compressed version is here:

 ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.5.4.tar.gz (1763k)
 ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.5.4.tar.gz.sig

Alternativley you may upgrade using this patch file:

 ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.5.3-1.5.4.diff.bz2 (17k)

In order to check that the version of Libgcrypt you are going to build
is an original and unmodified one, you can do it in one of the following
ways:

 * Check the supplied OpenPGP signature.  For example to check the
   signature of the file libgcrypt-1.5.4.tar.bz2 you would use this
   command:

     gpg --verify libgcrypt-1.5.4.tar.bz2.sig

   This checks whether the signature file matches the source file.  You
   should see a message indicating that the signature is good and made
   by the release signing key 4F25E3B6 which is certified by my well
   known key 1E42B367.  To retrieve the keys you may use the command
   "gpg --fetch-key finger:wk <at> g10code.com".

 * If you are not able to use GnuPG, you have to verify the SHA-1
   checksum:

     sha1sum libgcrypt-1.5.4.tar.bz2

   and check that the output matches the first line from the
   following list:

bdf4b04a0d2aabc04ab3564fbe38fd094135aa7a  libgcrypt-1.5.4.tar.bz2
71e432e0ae8792076a40c6059667997250abbb9d  libgcrypt-1.5.4.tar.gz
8876ae002751e6ec26c76e510d17fc3e0eccb3ed  libgcrypt-1.5.3-1.5.4.diff.bz2

Copying
=======

Libgcrypt is distributed under the terms of the GNU Lesser General
Public License (LGPLv2.1+).  The helper programs as well as the
documentation are distributed under the terms of the GNU General Public
License (GPLv2+).  The file LICENSES has notices about contributions
that require these additional notices are distributed.

Support
=======

For help on developing with Libgcrypt you should read the included
manual and optional ask on the gcrypt-devel mailing list [1].  A
listing with commercial support offers for Libgcrypt and related
software is available at the GnuPG web site [2].

The driving force behind the development of Libgcrypt is my company
g10 Code.  Maintenance and improvement of Libgcrypt and related
software takes up most of our resources.  To allow us to continue our
work on free software, we ask to either purchase a support contract,
engage us for custom enhancements, or to donate money:

  http://gnupg.org/donate/

Thanks
======

Many thanks to all who contributed to Libgcrypt development, be it bug
fixes, code, documentation, testing or helping users.

Happy hacking,

  Werner

[1] https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
[2] https://gnupg.org/service.html

--

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.
_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel

Gmane