[EXPERIMENTAL-PATCH] Curve25519 encryption support (updated)

NIIBE Yutaka gniibe at fsij.org
Tue Aug 4 16:19:48 CEST 2015


On 08/03/2015 08:00 PM, Werner Koch wrote:
> Right. So here is my final list
> 
>   - tweak
>   - djb-tweak
>   - setmsb
> 
> Whatever you like - it's your call.  Let's get that finished before
> Debconf

Yes.  I picked up "djb-tweak".  (It would be possible we will have
another tweak in future.)

Here is revised version.  It goes well with "make check".  Tested with
GnuPG and Gnuk.  I'll review this again to make a commit message.

I'll post revised GnuPG patch tomorrow.


PUBKEY_FLAG_DJB_TWEAK is added as a flag.  This is because it's
not the curve domain parameter which should change this behavior.

In theory, it is possible for the curve of Curve25519 (or any
Montgomery curve), to be used with no PUBKEY_FLAG_DJB_TWEAK, although
no one wants to that.  Besides, it is also possible for Weierstrass
curve to be used with PUBKEY_FLAG_DJB_TWEAK (this case is not
implemented yet).


diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index f0d97ea..4e528af 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -94,6 +94,9 @@ gcry_err_code_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value);
 mpi_point_t  _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
                                        mpi_point_t G, gcry_mpi_t d);

+gpg_err_code_t _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx,
+                                           mpi_point_t result);
+
 /*-- ecc.c --*/

 /*-- ecc-ecdsa.c --*/
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 9975bb4..51d9e39 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -40,7 +40,7 @@ static const struct
   const char *other; /* Other name. */
 } curve_aliases[] =
   {
-  /*{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },*/
+    { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
     { "Ed25519",    "1.3.6.1.4.1.11591.15.1" },

     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
@@ -107,7 +107,8 @@ typedef struct

   const char *p;              /* The prime defining the field.  */
   const char *a, *b;          /* The coefficients.  For Twisted Edwards
-                                 Curves b is used for d.  */
+                                 Curves b is used for d.  For Montgomery
+                                 Curves a has (A-2)/4.  */
   const char *n;              /* The order of the base point.  */
   const char *g_x, *g_y;      /* Base point.  */
   const char *h;              /* Cofactor.  */
@@ -129,6 +130,18 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x6666666666666666666666666666666666666666666666666666666666666658",
       "0x08"
     },
+    {
+      /* (y^2 = x^3 + 486662*x^2 + x) */
+      "Curve25519", 256, 0,
+      MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
+      "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
+      "0x01DB41",
+      "0x01",
+      "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
+      "0x0000000000000000000000000000000000000000000000000000000000000009",
+      "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
+      "0x08"
+    },
 #if 0 /* No real specs yet found.  */
     {
       /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 88266b5..982e150 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -287,3 +287,51 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,

   return Q;
 }
+
+
+gpg_err_code_t
+_gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
+{
+  unsigned char *rawmpi;
+  unsigned int rawmpilen;
+
+  if (mpi_is_opaque (pk))
+    {
+      const unsigned char *buf;
+      unsigned char *p;
+
+      buf = mpi_get_opaque (pk, &rawmpilen);
+      if (!buf)
+        return GPG_ERR_INV_OBJ;
+      rawmpilen = (rawmpilen + 7)/8;
+
+      if (rawmpilen > 1 && (rawmpilen%2) && buf[0] == 0x40)
+        {
+          rawmpilen--;
+          buf++;
+        }
+
+      rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
+      if (!rawmpi)
+        return gpg_err_code_from_syserror ();
+
+      p = rawmpi + rawmpilen;
+      while (p > rawmpi)
+        *--p = *buf++;
+    }
+  else
+    {
+      /* Note: Without using an opaque MPI it is not reliable possible
+         to find out whether the public key has been given in
+         uncompressed format.  Thus we expect native EdDSA format.  */
+      rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL);
+      if (!rawmpi)
+        return gpg_err_code_from_syserror ();
+    }
+
+  _gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0);
+  xfree (rawmpi);
+  mpi_set_ui (result->z, 1);
+
+  return 0;
+}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index e33f999..2f95ac4 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -81,7 +81,7 @@ 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 void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int flags);
 static unsigned int ecc_get_nbits (gcry_sexp_t parms);


@@ -142,7 +142,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
     random_level = GCRY_VERY_STRONG_RANDOM;

   /* Generate a secret.  */
-  if (ctx->dialect == ECC_DIALECT_ED25519)
+  if (ctx->dialect == ECC_DIALECT_ED25519 || (flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       char *rndbuf;

@@ -174,7 +174,10 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&sk->Q);

   x = mpi_new (pbits);
-  y = mpi_new (pbits);
+  if (r_y == NULL)
+    y = NULL;
+  else
+    y = mpi_new (pbits);
   if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
     log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");

@@ -187,7 +190,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * possibilities without any loss of security.  Note that we don't
    * do that for Ed25519 so that we do not violate the special
    * construction of the secret key.  */
-  if (E->dialect == ECC_DIALECT_ED25519)
+  if (r_y == NULL || E->dialect == ECC_DIALECT_ED25519)
     point_set (&sk->Q, &Q);
   else
     {
@@ -231,7 +234,8 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
     }

   *r_x = x;
-  *r_y = y;
+  if (r_y)
+    *r_y = y;

   point_free (&Q);
   /* Now we can test our keys (this should never fail!).  */
@@ -240,7 +244,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   else if (sk->E.model != MPI_EC_MONTGOMERY)
     test_keys (sk, nbits - 64);
   else
-    test_ecdh_only_keys (sk, nbits - 64);
+    test_ecdh_only_keys (sk, nbits - 64, flags);

   return 0;
 }
@@ -298,7 +302,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)


 static void
-test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)
+test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
 {
   ECC_public_key pk;
   gcry_mpi_t test;
@@ -307,7 +311,7 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)
   mpi_ec_t ec;

   if (DBG_CIPHER)
-    log_debug ("Testing key.\n");
+    log_debug ("Testing ECDH only key.\n");

   point_init (&R_);

@@ -315,7 +319,7 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)
   point_init (&pk.Q);
   point_set (&pk.Q, &sk->Q);

-  if (sk->E.dialect == ECC_DIALECT_ED25519)
+  if ((flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       char *rndbuf;

@@ -340,7 +344,7 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)

   /* R_ = hkQ  <=>  R_ = hkdG  */
   _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
-  if (sk->E.dialect != ECC_DIALECT_ED25519)
+  if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
     _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");
@@ -348,7 +352,7 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits)
   _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)
+  if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
     _gcry_mpi_ec_mul_point (&R_, ec->h, &R_, ec);

   if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
@@ -408,7 +412,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }

   /* Check order of curve.  */
-  if (sk->E.dialect != ECC_DIALECT_ED25519)
+  if (sk->E.dialect != ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
       if (mpi_cmp_ui (Q.z, 0))
@@ -571,7 +575,9 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)

   ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, 0, E.p, E.a, E.b);

-  if ((flags & PUBKEY_FLAG_EDDSA))
+  if (E.model == MPI_EC_MONTGOMERY)
+    rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, NULL);
+  else if ((flags & PUBKEY_FLAG_EDDSA))
     rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, flags);
   else
     rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, &Qy);
@@ -581,18 +587,38 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
   /* Copy data to the result.  */
   Gx = mpi_new (0);
   Gy = mpi_new (0);
-  if (_gcry_mpi_ec_get_affine (Gx, Gy, &sk.E.G, ctx))
-    log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
-  base = _gcry_ecc_ec2os (Gx, Gy, sk.E.p);
-  if (sk.E.dialect == ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_NOCOMP))
+  if (E.model != MPI_EC_MONTGOMERY)
+    {
+      if (_gcry_mpi_ec_get_affine (Gx, Gy, &sk.E.G, ctx))
+        log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
+      base = _gcry_ecc_ec2os (Gx, Gy, sk.E.p);
+    }
+  if ((sk.E.dialect == ECC_DIALECT_ED25519 || E.model == MPI_EC_MONTGOMERY)
+      && !(flags & PUBKEY_FLAG_NOCOMP))
     {
       unsigned char *encpk;
       unsigned int encpklen;

-      /* (Gx and Gy are used as scratch variables)  */
-      rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, Gx, Gy,
-                                        !!(flags & PUBKEY_FLAG_COMP),
-                                        &encpk, &encpklen);
+      if (E.model != MPI_EC_MONTGOMERY)
+        /* (Gx and Gy are used as scratch variables)  */
+        rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, Gx, Gy,
+                                          !!(flags & PUBKEY_FLAG_COMP),
+                                          &encpk, &encpklen);
+      else
+        {
+          int off = !!(flags & PUBKEY_FLAG_COMP);
+
+          encpk = _gcry_mpi_get_buffer_extra (Qx, ctx->nbits/8, off?-1:0,
+                                              &encpklen, NULL);
+          if (encpk == NULL)
+            rc = gpg_err_code_from_syserror ();
+          else
+            {
+              if (off)
+                encpk[0] = 0x40;
+              encpklen += off;
+            }
+        }
       if (rc)
         goto leave;
       public = mpi_new (0);
@@ -619,15 +645,18 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         goto leave;
     }

-  if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA))
+  if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA)
+      || (flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       rc = sexp_build
         (&curve_flags, NULL,
          ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
          "(flags param eddsa)" :
+         ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
+         "(flags param djb-tweak)" :
          ((flags & PUBKEY_FLAG_PARAM))?
-         "(flags param)" :
-         "(flags eddsa)");
+         "(flags param)" : ((flags & PUBKEY_FLAG_EDDSA))?
+         "(flags eddsa)" : "(flags djb-tweak)" );
       if (rc)
         goto leave;
     }
@@ -1214,11 +1243,23 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_mpi_t data = NULL;
   ECC_public_key pk;
   mpi_ec_t ec = NULL;
+  int flags;

   memset (&pk, 0, sizeof pk);
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
                                    ecc_get_nbits (keyparms));

+  /* Look for flags. */
+  l1 = sexp_find_token (keyparms, "flags", 0);
+  if (l1)
+    {
+      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
+      if (rc)
+        goto leave;
+    }
+  sexp_release (l1);
+  l1 = NULL;
+
   /*
    * Extract the data.
    */
@@ -1237,7 +1278,9 @@ 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?h?+q",
+  rc = sexp_extract_param (keyparms, NULL,
+                           (flags & PUBKEY_FLAG_DJB_TWEAK)?
+                           "-p?a?b?g?n?h?/q" : "-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)
@@ -1289,26 +1332,34 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       goto leave;
     }

+  /* Compute the encrypted value.  */
+  ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
+                                    pk.E.p, pk.E.a, pk.E.b);
+
   /* Convert the public key.  */
   if (mpi_q)
     {
       point_init (&pk.Q);
-      rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
+      if (ec->model == MPI_EC_MONTGOMERY)
+        rc = _gcry_ecc_mont_decodepoint (mpi_q, ec, &pk.Q);
+      else
+        rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
       if (rc)
         goto leave;
     }

-  /* Compute the encrypted value.  */
-  ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
-                                    pk.E.p, pk.E.a, pk.E.b);
-
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
   {
     mpi_point_struct R;  /* Result that we return.  */
     gcry_mpi_t x, y;
+    unsigned char *rawmpi;
+    unsigned int rawmpilen;

     x = mpi_new (0);
-    y = mpi_new (0);
+    if (ec->model == MPI_EC_MONTGOMERY)
+      y = NULL;
+    else
+      y = mpi_new (0);

     point_init (&R);

@@ -1317,14 +1368,39 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)

     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
       log_fatal ("ecdh: Failed to get affine coordinates for kdG\n");
-    mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
+    if (y)
+      mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
+    else
+      {
+        rawmpi = _gcry_mpi_get_buffer (x, ec->nbits/8, &rawmpilen, NULL);
+        if (!rawmpi)
+          rc = gpg_err_code_from_syserror ();
+        else
+          {
+            mpi_s = mpi_new (0);
+            mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8);
+          }
+      }

     /* R = kG */
     _gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec);

     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
       log_fatal ("ecdh: Failed to get affine coordinates for kG\n");
-    mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p);
+    if (y)
+      mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p);
+    else
+      {
+        rawmpi = _gcry_mpi_get_buffer (x, ec->nbits/8, &rawmpilen, NULL);
+        if (!rawmpi)
+          rc = gpg_err_code_from_syserror ();
+        else
+          {
+            mpi_e = mpi_new (0);
+            mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8);
+          }
+      }
+

     mpi_free (x);
     mpi_free (y);
@@ -1332,7 +1408,8 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     point_free (&R);
   }

-  rc = sexp_build (r_ciph, NULL, "(enc-val(ecdh(s%m)(e%m)))", mpi_s, mpi_e);
+  if (!rc)
+    rc = sexp_build (r_ciph, NULL, "(enc-val(ecdh(s%m)(e%m)))", mpi_s, mpi_e);

  leave:
   _gcry_mpi_release (pk.E.p);
@@ -1348,6 +1425,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_mpi_release (mpi_s);
   _gcry_mpi_release (mpi_e);
   xfree (curvename);
+  sexp_release (l1);
   _gcry_mpi_ec_free (ec);
   _gcry_pk_util_free_encoding_ctx (&ctx);
   if (DBG_CIPHER)
@@ -1377,6 +1455,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   mpi_point_struct kG;
   mpi_point_struct R;
   gcry_mpi_t r = NULL;
+  int flags = 0;

   memset (&sk, 0, sizeof sk);
   point_init (&kG);
@@ -1385,6 +1464,17 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
                                    ecc_get_nbits (keyparms));

+  /* Look for flags. */
+  l1 = sexp_find_token (keyparms, "flags", 0);
+  if (l1)
+    {
+      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
+      if (rc)
+        goto leave;
+    }
+  sexp_release (l1);
+  l1 = NULL;
+
   /*
    * Extract the data.
    */
@@ -1459,16 +1549,19 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     }


+  ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, 0,
+                                    sk.E.p, sk.E.a, sk.E.b);
+
   /*
    * Compute the plaintext.
    */
-  rc = _gcry_ecc_os2ec (&kG, data_e);
+  if (ec->model == MPI_EC_MONTGOMERY)
+    rc = _gcry_ecc_mont_decodepoint (data_e, ec, &kG);
+  else
+    rc = _gcry_ecc_os2ec (&kG, data_e);
   if (rc)
     goto leave;

-  ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, 0,
-                                    sk.E.p, sk.E.a, sk.E.b);
-
   /* R = dkG */
   _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);

@@ -1477,12 +1570,30 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     gcry_mpi_t x, y;

     x = mpi_new (0);
-    y = mpi_new (0);
+    if (ec->model == MPI_EC_MONTGOMERY)
+      y = NULL;
+    else
+      y = mpi_new (0);

     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
       log_fatal ("ecdh: Failed to get affine coordinates\n");

-    r = _gcry_ecc_ec2os (x, y, sk.E.p);
+    if (y)
+      r = _gcry_ecc_ec2os (x, y, sk.E.p);
+    else
+      {
+        unsigned char *rawmpi;
+        unsigned int rawmpilen;
+
+        rawmpi = _gcry_mpi_get_buffer (x, ec->nbits/8, &rawmpilen, NULL);
+        if (!rawmpi)
+          rc = gpg_err_code_from_syserror ();
+        else
+          {
+            r = mpi_new (0);
+            mpi_set_opaque (r, rawmpi, rawmpilen*8);
+          }
+      }
     if (!r)
       rc = gpg_err_code_from_syserror ();
     else
@@ -1604,7 +1715,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
   /* Extract the parameters.  */
   if ((flags & PUBKEY_FLAG_PARAM))
     {
-      if ((flags & PUBKEY_FLAG_EDDSA))
+      if ((flags & PUBKEY_FLAG_DJB_TWEAK))
         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],
@@ -1617,7 +1728,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
     }
   else
     {
-      if ((flags & PUBKEY_FLAG_EDDSA))
+      if ((flags & PUBKEY_FLAG_DJB_TWEAK))
         rc = sexp_extract_param (keyparms, NULL, "/q",
                                  &values[6], NULL);
       else
@@ -1674,12 +1785,9 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
      the compressed version.  Because we don't support any non-eddsa
      compression, the only thing we need to do is to compress
      EdDSA.  */
-  if ((flags & PUBKEY_FLAG_EDDSA))
+  if ((flags & PUBKEY_FLAG_DJB_TWEAK))
     {
-      if (dialect == ECC_DIALECT_ED25519)
-        rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
-      else
-        rc = GPG_ERR_NOT_IMPLEMENTED;
+      rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
       if (rc)
         goto leave;
     }
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index afa3454..b958e7d 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -107,6 +107,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
             {
               encoding = PUBKEY_ENC_RAW;
               flags |= PUBKEY_FLAG_EDDSA;
+              flags |= PUBKEY_FLAG_DJB_TWEAK;
             }
           else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
             {
@@ -142,12 +143,17 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
             rc = GPG_ERR_INV_FLAG;
           break;

-	case 9:
+        case 9:
           if (!memcmp (s, "pkcs1-raw", 9) && encoding == PUBKEY_ENC_UNKNOWN)
             {
               encoding = PUBKEY_ENC_PKCS1_RAW;
               flags |= PUBKEY_FLAG_FIXEDLEN;
             }
+          else if (!memcmp (s, "djb-tweak", 9))
+            {
+              encoding = PUBKEY_ENC_RAW;
+              flags |= PUBKEY_FLAG_DJB_TWEAK;
+            }
           else if (!igninvflag)
             rc = GPG_ERR_INV_FLAG;
           break;
diff --git a/src/cipher.h b/src/cipher.h
index 52f2695..89ae2e2 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -41,6 +41,7 @@
 #define PUBKEY_FLAG_EDDSA          (1 << 12)
 #define PUBKEY_FLAG_GOST           (1 << 13)
 #define PUBKEY_FLAG_NO_KEYTEST     (1 << 14)
+#define PUBKEY_FLAG_DJB_TWEAK      (1 << 15)


 enum pk_operation
diff --git a/tests/curves.c b/tests/curves.c
index 178a192..bec48e9 100644
--- a/tests/curves.c
+++ b/tests/curves.c
@@ -29,7 +29,7 @@
 #include "../src/gcrypt-int.h"

 /* Number of curves defined in ../cipger/ecc.c */
-#define N_CURVES 21
+#define N_CURVES 22

 /* A real world sample public key.  */
 static char const sample_key_1[] =
--



More information about the Gcrypt-devel mailing list