[PATCH] Curve25519 patch revised

NIIBE Yutaka gniibe at fsij.org
Thu Aug 7 07:47:27 CEST 2014


On 2014-07-21 at 17:35 +0200, Werner Koch wrote:
> On Wed, 16 Jul 2014 16:02, gniibe at fsij.org said:
> > Here is a patch adding cofactor to the domain parameters of ECC.
> >
> > Note that this introduce KEYGRIP value change.
> 
> That is bad.  Why not exclude it from the keygrip computation?

I see, excluding the cofactor is better (to be compatible).

Here is the patch keeping compute_keygrip untouched.

OK to commit?

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
@@ -32,6 +32,7 @@ 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;
 
@@ -75,7 +76,7 @@ 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
@@ -110,6 +110,7 @@ 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;
 

@@ -125,7 +126,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
-      "0x6666666666666666666666666666666666666666666666666666666666666658"
+      "0x6666666666666666666666666666666666666666666666666666666666666658",
+      "0x08"
     },
 #if 0 /* No real specs yet found.  */
     {
@@ -140,7 +142,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "706022B36F1C0338AD63CF181B0E71A5E106AF79",
       "0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
       "6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
-      "0x22"
+      "0x22",
+      "0x08"
     },
 #endif /*0*/
     {
@@ -152,7 +155,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
 
       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
-      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
+      "0x01"
     },
     {
       "NIST P-224", 224, 1,
@@ -163,7 +167,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
 
       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
+      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+      "0x01"
     },
     {
       "NIST P-256", 256, 1,
@@ -174,7 +179,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
 
       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
-      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+      "0x01"
     },
     {
       "NIST P-384", 384, 1,
@@ -191,7 +197,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
       "5502f25dbf55296c3a545e3872760ab7",
       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
-      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
+      "0a60b1ce1d7e819d7a431d7c90ea0e5f",
+      "0x01"
     },
     {
       "NIST P-521", 521, 1,
@@ -208,7 +215,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
       "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
       "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
-      "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+      "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
+      "0x01"
     },
 
     { "brainpoolP160r1", 160, 0,
@@ -218,7 +226,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
-      "0x1667cb477a1a8ec338f94741669c976316da6321"
+      "0x1667cb477a1a8ec338f94741669c976316da6321",
+      "0x01"
     },
 
     { "brainpoolP192r1", 192, 0,
@@ -228,7 +237,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
-      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
+      "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
+      "0x01"
     },
 
     { "brainpoolP224r1", 224, 0,
@@ -238,7 +248,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
-      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
+      "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
+      "0x01"
     },
 
     { "brainpoolP256r1", 256, 0,
@@ -248,7 +259,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
-      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
+      "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
+      "0x01"
     },
 
     { "brainpoolP320r1", 320, 0,
@@ -264,7 +276,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
       "10af8d0d39e20611",
       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
-      "d35245d1692e8ee1"
+      "d35245d1692e8ee1",
+      "0x01"
     },
 
     { "brainpoolP384r1", 384, 0,
@@ -280,7 +293,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
       "e826e03436d646aaef87b2e247d4af1e",
       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
-      "0e4646217791811142820341263c5315"
+      "0e4646217791811142820341263c5315",
+      "0x01"
     },
 
     { "brainpoolP512r1", 512, 0,
@@ -296,7 +310,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
-      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
+      "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
+      "0x01"
     },
     {
       "GOST2001-test", 256, 0,
@@ -308,6 +323,7 @@ static const ecc_domain_parms_t domain_parms[] =
 
       "0x0000000000000000000000000000000000000000000000000000000000000002",
       "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-A", 256, 0,
@@ -317,7 +333,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x00000000000000000000000000000000000000000000000000000000000000a6",
       "0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
-      "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14"
+      "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-B", 256, 0,
@@ -327,7 +344,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x3e1af419a269a5f866a7d3c25c3df80ae979259373ff2b182f49d4ce7e1bbc8b",
       "0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
-      "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc"
+      "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
+      "0x01"
     },
     {
       "GOST2001-CryptoPro-C", 256, 0,
@@ -337,7 +355,8 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x000000000000000000000000000000000000000000000000000000000000805a",
       "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
       "0x0000000000000000000000000000000000000000000000000000000000000000",
-      "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67"
+      "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
+      "0x01"
     },
     {
       "GOST2012-test", 511, 0,
@@ -354,6 +373,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
       "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
       "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
+      "0x01"
     },
     {
       "GOST2012-tc26-A", 512, 0,
@@ -370,6 +390,7 @@ static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000003",
       "0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
         "df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
+      "0x01"
     },
     {
       "GOST2012-tc26-B", 512, 0,
@@ -386,6 +407,7 @@ static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000002",
       "0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
         "dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
+      "0x01"
     },
 
     {
@@ -396,10 +418,11 @@ 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 }
   };
 

@@ -530,6 +553,8 @@ _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)
@@ -545,7 +570,7 @@ _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
@@ -553,7 +578,7 @@ _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;
 
@@ -603,6 +628,11 @@ _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;
 }
 
@@ -640,8 +670,8 @@ _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)
     {
@@ -699,17 +729,22 @@ _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;
+                                }
                             }
                         }
                     }
@@ -726,6 +761,7 @@ _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;
 }
 
@@ -857,6 +893,7 @@ _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;
@@ -899,6 +936,9 @@ _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
@@ -972,6 +1012,11 @@ _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);
     }
@@ -998,6 +1043,11 @@ _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
@@ -1036,6 +1086,7 @@ _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;
@@ -1050,7 +1101,7 @@ _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;
 
@@ -1074,14 +1125,15 @@ _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++)
@@ -1108,6 +1160,8 @@ _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);
 
@@ -1206,6 +1260,11 @@ _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] == '@'))
     {
       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
@@ -525,6 +525,7 @@ _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
@@ -43,6 +43,7 @@ _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;
 }
 

@@ -63,6 +64,7 @@ _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..8eb7ba4 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -142,6 +142,7 @@ 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
@@ -456,6 +457,7 @@ 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);
     }
 
@@ -524,14 +526,14 @@ 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"
@@ -554,6 +556,7 @@ 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))
@@ -604,9 +607,9 @@ 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);
@@ -624,7 +627,7 @@ 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;
         }
@@ -660,11 +663,12 @@ 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;
@@ -701,6 +705,7 @@ 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);
@@ -741,9 +746,9 @@ 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);
@@ -793,11 +798,12 @@ 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;
@@ -838,6 +844,7 @@ 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);
@@ -905,9 +912,9 @@ 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);
@@ -958,9 +965,10 @@ 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;
@@ -1036,6 +1044,7 @@ 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);
@@ -1115,8 +1124,8 @@ 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;
@@ -1159,9 +1168,10 @@ 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    n", 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;
@@ -1219,6 +1229,7 @@ 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);
@@ -1282,9 +1293,9 @@ 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)
@@ -1325,10 +1336,11 @@ 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;
@@ -1385,6 +1397,7 @@ 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);
@@ -1624,7 +1637,7 @@ _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)
@@ -1676,15 +1689,15 @@ _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;
@@ -1744,7 +1757,7 @@ 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
@@ -429,6 +429,7 @@ 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
@@ -38,6 +38,7 @@ 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
@@ -41,6 +41,7 @@ static char const sample_key_1[] =
 "  (g #046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
         "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5#)\n"
 "  (n #00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551#)\n"
+"  (h #000000000000000000000000000000000000000000000000000000000000000001#)\n"
 "  (q #0442B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146EE"
       "86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E#)\n"
 "  ))";
@@ -57,6 +58,7 @@ 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..717535d 100644
--- a/tests/keygrip.c
+++ b/tests/keygrip.c
@@ -110,8 +110,9 @@ 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"
+      "\xE6\xBA\x0B\x38\xFC\xD0\x5C\x74\x47\x4C\x8E\x92\xD5\xCA\xE4\x69\xED\xEB\xC9\x1F"
     },
     {
       GCRY_PK_ECDSA,
@@ -122,8 +123,9 @@ 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"
+      "\xE6\xBA\x0B\x38\xFC\xD0\x5C\x74\x47\x4C\x8E\x92\xD5\xCA\xE4\x69\xED\xEB\xC9\x1F"
     },
     {
       GCRY_PK_ECDSA,
@@ -134,8 +136,9 @@ 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"
+      "\xE6\xBA\x0B\x38\xFC\xD0\x5C\x74\x47\x4C\x8E\x92\xD5\xCA\xE4\x69\xED\xEB\xC9\x1F"
     },
     {
       GCRY_PK_ECDSA,
@@ -143,7 +146,7 @@ static struct
       " (ecdsa"
       " (curve secp256r1)"
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
-      "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
+      "\xE6\xBA\x0B\x38\xFC\xD0\x5C\x74\x47\x4C\x8E\x92\xD5\xCA\xE4\x69\xED\xEB\xC9\x1F"
     },
     {
       GCRY_PK_ECC,
@@ -151,7 +154,7 @@ static struct
       " (ecc"
       " (curve secp256r1)"
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
-      "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
+      "\xE6\xBA\x0B\x38\xFC\xD0\x5C\x74\x47\x4C\x8E\x92\xD5\xCA\xE4\x69\xED\xEB\xC9\x1F"
     },
     { /* Ed25519 standard */
       GCRY_PK_ECC,
@@ -162,8 +165,8 @@ static struct
       "     1CC662926E7EFF4982B7FB8B928E61CD74CCDD85277CC57196C3AD20B611085F"
       "     47BD24842905C049257673B3F5249524E0A41FAA17B25B818D0F97E625F1A1D0#)"
       "     ))",
-      "\x0C\xCA\xB2\xFD\x48\x9A\x33\x40\x2C\xE8"
-      "\xE0\x4A\x1F\xB2\x45\xEA\x80\x3D\x0A\xF1"
+      "\x9F\x7F\xED\x00\x5C\x18\x7C\x07\x01\x7D"
+      "\xFC\xF2\xA2\xD4\xD1\xCE\x11\x59\x4F\x72"
     },
     { /* Ed25519+EdDSA */
       GCRY_PK_ECC,
@@ -172,8 +175,8 @@ static struct
       " (curve Ed25519)(flags eddsa)"
       " (q #773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)"
       " ))",
-      "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70"
-      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47"
+      "\x06\xCC\xA3\x1F\x4D\x23\x08\xF7\x91\xA2"
+      "\x48\xF7\x0E\x41\x4A\x70\x76\xC2\xA4\x95"
     },
     { /* Ed25519+EdDSA (with compression prefix) */
       GCRY_PK_ECC,
@@ -195,8 +198,8 @@ static struct
       "     629ad237d1ed04dcd4abe1711dd699a1cf51b1584c4de7a4ef8b8a640180b26f"
       "     5bb7c29018ece0f46b01f2960e99041a5779afe7e2292b65f9d51f8c84723e77#)"
       " ))",
-      "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70"
-      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47"
+      "\x06\xCC\xA3\x1F\x4D\x23\x08\xF7\x91\xA2"
+      "\x48\xF7\x0E\x41\x4A\x70\x76\xC2\xA4\x95"
     }
   };
 
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
@@ -57,6 +57,7 @@ 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[] =
   {
     {
@@ -67,7 +68,8 @@ static struct
       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
 
       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
-      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+      "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
+      "0x01"
     },
     {
       "NIST P-224",
@@ -77,7 +79,8 @@ static struct
       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
 
       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
-      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
+      "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
+      "0x01"
     },
     {
       "NIST P-256",
@@ -87,7 +90,8 @@ static struct
       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
 
       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
-      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+      "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+      "0x01"
     },
     {
       "NIST P-384",
@@ -103,7 +107,8 @@ static struct
       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
       "5502f25dbf55296c3a545e3872760ab7",
       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
-      "0a60b1ce1d7e819d7a431d7c90ea0e5f"
+      "0a60b1ce1d7e819d7a431d7c90ea0e5f",
+      "0x01"
     },
     {
       "NIST P-521",
@@ -119,7 +124,8 @@ static struct
       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
-      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
+      "0x01"
     },
     {
       "Ed25519",
@@ -128,9 +134,10 @@ 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.  */
@@ -556,6 +563,8 @@ 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;
 
     }
 
-- 





More information about the Gcrypt-devel mailing list