[TESTING] Curve25519 encryption support (update-2)

NIIBE Yutaka gniibe at fsij.org
Wed Aug 5 13:34:30 CEST 2015


On 08/05/2015 03:40 PM, Werner Koch wrote:
> Without the alias we change how we print such a key: Now it is
> 
>   sec   ed25519/E3FDFF218E45B72B 2015-02-18 [expires: 2025-02-15]
> 
> but with the change this will be
> 
>   sec   Ed25519/E3FDFF218E45B72B 2015-02-18 [expires: 2025-02-15]
> 
> (see g10/keyid.c:pubkey_string) I'd very much like to have the
> algo/curve in lowercase.

Sorry.  My badness.  I was not careful enough for printing.

> What about 
> 
>  /* Map an OpenPGP OID to the Libgcrypt curve NAME.  Returns NULL for
> -   unknown curve names.  We prefer an alias name here which is more
> -   suitable for printing.  */
> +   unknown curve names.  Unless CANON is set we prefer an alias name
> +   here which is more suitable for printing.  */
>  const char *
> -openpgp_oid_to_curve (const char *oidstr)
> +openpgp_oid_to_curve (const char *oidstr, int canon)
>  {
>    int i;
>  

OK.  I prefer CANON.  With a bit different spelling, we have a statue
(of Buddhism) in our prefecture:

    http://takasakikannon.or.jp/images/about/kannon.jpg


Here is the revised version, including your suggestion.


diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 562179b..39ccba2 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -83,14 +83,25 @@ get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
     case GCRY_PK_ECC:
       if (!curve)
         err = gpg_error (GPG_ERR_BAD_SECKEY);
-      else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
-        err = gcry_sexp_build (&s_pkey, NULL,
-                               "(public-key(ecc(curve %s)(flags eddsa)(q%m)))",
-                               "Ed25519", pkey[0]);
       else
-        err = gcry_sexp_build (&s_pkey, NULL,
-                               "(public-key(ecc(curve %s)(q%m)))",
-                               curve, pkey[0]);
+        {
+          const char *format;
+
+          if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+            {
+              format = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))";
+              curve = "Ed25519";
+            }
+          else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
+            {
+              format = "(public-key(ecc(curve %s)(flags djb-tweak)(q%m)))";
+              curve = "Curve25519";
+            }
+          else
+            format = "(public-key(ecc(curve %s)(q%m)))";
+
+          err = gcry_sexp_build (&s_pkey, NULL, format, curve, pkey[0]);
+        }
       break;

     default:
@@ -146,19 +157,27 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
     case GCRY_PK_ECC:
       if (!curve)
         err = gpg_error (GPG_ERR_BAD_SECKEY);
-      else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+      else
         {
-          /* Do not store the OID as name but the real name and the
-             EdDSA flag.  */
-          err = gcry_sexp_build (&s_skey, NULL,
-                                 "(private-key(ecc(curve%s)(flags eddsa)"
-                                 "(q%m)(d%m)))",
-                                 "Ed25519", skey[0], skey[1]);
+          const char *format;
+
+          if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+            {
+              /* Do not store the OID as name but the real name and the
+                 EdDSA flag.  */
+              format = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))";
+              curve = "Ed25519";
+            }
+          else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
+            {
+              format = "(private-key(ecc(curve %s)(flags djb-tweak)(q%m)(d%m)))";
+              curve = "Curve25519";
+            }
+          else
+            format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
+
+          err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
         }
-      else
-        err = gcry_sexp_build (&s_skey, NULL,
-                               "(private-key(ecc(curve%s)(q%m)(d%m)))",
-                               curve, skey[0], skey[1]);
       break;

     default:
@@ -216,22 +235,30 @@ convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
     case GCRY_PK_ECC:
       if (!curve)
         err = gpg_error (GPG_ERR_BAD_SECKEY);
-      else if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+      else
         {
-          /* Do not store the OID as name but the real name and the
-             EdDSA flag.  */
-          err = gcry_sexp_build
-            (&s_skey, NULL,
-             "(protected-private-key(ecc(curve%s)(flags eddsa)(q%m)"
-             "(protected openpgp-native%S)))",
-             "Ed25519", skey[0], transfer_key);
+          const char *format;
+
+          if (!strcmp (curve, openpgp_curve_to_oid ("Ed25519", NULL)))
+            {
+              /* Do not store the OID as name but the real name and the
+                 EdDSA flag.  */
+              format = "(protected-private-key(ecc(curve %s)(flags eddsa)(q%m)"
+                "(protected openpgp-native%S)))";
+              curve = "Ed25519";
+            }
+          else if (!strcmp (curve, openpgp_curve_to_oid ("Curve25519", NULL)))
+            {
+              format = "(protected-private-key(ecc(curve %s)(flags djb-tweak)(q%m)"
+                "(protected openpgp-native%S)))";
+              curve = "Curve25519";
+            }
+          else
+              format = "(protected-private-key(ecc(curve %s)(q%m)"
+                "(protected openpgp-native%S)))";
+
+          err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], transfer_key);
         }
-      else
-        err = gcry_sexp_build
-          (&s_skey, NULL,
-           "(protected-private-key(ecc(curve%s)(q%m)"
-           "(protected openpgp-native%S)))",
-           curve, skey[0], transfer_key);
       break;

     default:
diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c
index 676079c..580084d 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -45,6 +45,7 @@ static struct {
   const char *alias;  /* NULL or alternative name of the curve.  */
 } oidtable[] = {

+  { "Curve25519",      "1.3.6.1.4.1.3029.1.5.1", 255, "crv25519" },
   { "Ed25519",         "1.3.6.1.4.1.11591.15.1", 255, "ed25519" },

   { "NIST P-256",      "1.2.840.10045.3.1.7",    256, "nistp256" },
@@ -65,6 +66,10 @@ static struct {
 static const char oid_ed25519[] =
   { 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };

+/* The OID for Curve25519 in OpenPGP format.  */
+static const char oid_curve25519[] =
+  { 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
+

 /* Helper for openpgp_oid_from_str.  */
 static size_t
@@ -291,6 +296,22 @@ openpgp_oid_is_ed25519 (gcry_mpi_t a)
 }


+int
+openpgp_oid_is_curve25519 (gcry_mpi_t a)
+{
+  const unsigned char *buf;
+  unsigned int nbits;
+  size_t n;
+
+  if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+    return 0;
+
+  buf = gcry_mpi_get_opaque (a, &nbits);
+  n = (nbits+7)/8;
+  return (n == DIM (oid_curve25519)
+          && !memcmp (buf, oid_curve25519, DIM (oid_curve25519)));
+}
+

 /* Map the Libgcrypt ECC curve NAME to an OID.  If R_NBITS is not NULL
    store the bit size of the curve there.  Returns NULL for unknown
@@ -333,10 +354,10 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits)


 /* Map an OpenPGP OID to the Libgcrypt curve NAME.  Returns NULL for
-   unknown curve names.  We prefer an alias name here which is more
-   suitable for printing.  */
+   unknown curve names.  Unless CANON is set we prefer an alias name
+   here which is more suitable for printing.  */
 const char *
-openpgp_oid_to_curve (const char *oidstr)
+openpgp_oid_to_curve (const char *oidstr, int canon)
 {
   int i;

@@ -345,7 +366,7 @@ openpgp_oid_to_curve (const char *oidstr)

   for (i=0; oidtable[i].name; i++)
     if (!strcmp (oidtable[i].oidstr, oidstr))
-      return oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
+      return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;

   return NULL;
 }
diff --git a/common/util.h b/common/util.h
index 90acefa..113ed8a 100644
--- a/common/util.h
+++ b/common/util.h
@@ -322,8 +322,9 @@ size_t percent_unescape_inplace (char *string, int nulrepl);
 gpg_error_t openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi);
 char *openpgp_oid_to_str (gcry_mpi_t a);
 int openpgp_oid_is_ed25519 (gcry_mpi_t a);
+int openpgp_oid_is_curve25519 (gcry_mpi_t a);
 const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits);
-const char *openpgp_oid_to_curve (const char *oid);
+const char *openpgp_oid_to_curve (const char *oid, int canon);
 const char *openpgp_enum_curves (int *idxp);


diff --git a/g10/ecdh.c b/g10/ecdh.c
index 9576a1c..a1b7ecf 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -134,9 +134,12 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
       }

     secret_x_size = (nbits+7)/8;
-    assert (nbytes > secret_x_size);
-    memmove (secret_x, secret_x+1, secret_x_size);
-    memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
+    assert (nbytes >= secret_x_size);
+    if ((nbytes & 1))
+      /* Remove the "04" prefix of non-compressed format.  */
+      memmove (secret_x, secret_x+1, secret_x_size);
+    if (nbytes - secret_x_size)
+      memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);

     if (DBG_CRYPTO)
       log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
diff --git a/g10/import.c b/g10/import.c
index 0a2ebcd..e92769d 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1414,7 +1414,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
             err = gpg_error_from_syserror ();
           else
             {
-              const char *curvename = openpgp_oid_to_curve (curvestr);
+              const char *curvename = openpgp_oid_to_curve (curvestr, 1);
               err = gcry_sexp_build (&curve, NULL, "(curve %s)",
                                      curvename?curvename:curvestr);
               xfree (curvestr);
diff --git a/g10/keygen.c b/g10/keygen.c
index 796d18f..f03c148 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1520,6 +1520,13 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
        (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
          && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
         " transient-key" : ""));
+  else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519"))
+    keyparms = xtryasprintf
+      ("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
+       strlen (curve), curve,
+       (((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
+         && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
+        " transient-key" : ""));
   else
     keyparms = xtryasprintf
       ("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
@@ -2125,7 +2132,7 @@ ask_keysize (int algo, unsigned int primary_keysize)
    function may adjust.  Returns a malloced string with the name of
    the curve.  BOTH tells that gpg creates a primary and subkey. */
 static char *
-ask_curve (int *algo, int both)
+ask_curve (int *algo, int *subkey_algo)
 {
   struct {
     const char *name;
@@ -2176,7 +2183,7 @@ ask_curve (int *algo, int both)
         continue;
       if (!gcry_pk_get_curve (keyparms, 0, NULL))
         continue;
-      if (both && curves[idx].fix_curve)
+      if (subkey_algo && curves[idx].fix_curve)
         {
           /* Both Curve 25519 keys are to be created.  Check that
              Libgcrypt also supports the real Curve25519.  */
@@ -2241,6 +2248,11 @@ ask_curve (int *algo, int both)
           if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA)
               && curves[idx].fix_curve)
             {
+              if (subkey_algo && *subkey_algo == PUBKEY_ALGO_ECDSA)
+                {
+                  *subkey_algo = PUBKEY_ALGO_EDDSA;
+                  result = xstrdup ("Ed25519");
+                }
               *algo = PUBKEY_ALGO_EDDSA;
               result = xstrdup ("Ed25519");
             }
@@ -3672,7 +3684,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo, both);
+              curve = ask_curve (&algo, &subkey_algo);
               r = xmalloc_clear( sizeof *r + 20 );
               r->key = pKEYTYPE;
               sprintf( r->u.value, "%d", algo);
@@ -3743,7 +3755,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo, 0);
+              curve = ask_curve (&algo, NULL);
               nbits = 0;
               r = xmalloc_clear (sizeof *r + strlen (curve));
               r->key = pKEYCURVE;
@@ -4292,7 +4304,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
   else if (algo == PUBKEY_ALGO_ECDSA
            || algo == PUBKEY_ALGO_EDDSA
            || algo == PUBKEY_ALGO_ECDH)
-    curve = ask_curve (&algo, 0);
+    curve = ask_curve (&algo, NULL);
   else
     nbits = ask_keysize (algo, 0);

diff --git a/g10/keyid.c b/g10/keyid.c
index 6b6f670..9ccee6e 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -119,7 +119,7 @@ pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize)
   else if (prefix)
     {
       char *curve = openpgp_oid_to_str (pk->pkey[0]);
-      const char *name = openpgp_oid_to_curve (curve);
+      const char *name = openpgp_oid_to_curve (curve, 0);

       if (name)
         snprintf (buffer, bufsize, "%s", name);
@@ -766,9 +766,12 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
         else
           {
             err = gcry_sexp_build (&s_pkey, NULL,
-                                   pk->pubkey_algo == PUBKEY_ALGO_EDDSA ?
-                                   "(public-key(ecc(curve%s)(flags eddsa)(q%m)))"
-                                   : "(public-key(ecc(curve%s)(q%m)))",
+                                   pk->pubkey_algo == PUBKEY_ALGO_EDDSA?
+                                   "(public-key(ecc(curve%s)(flags eddsa)(q%m)))":
+                                   (pk->pubkey_algo == PUBKEY_ALGO_ECDH
+                                    && openpgp_oid_is_curve25519 (pk->pkey[0]))?
+                                   "(public-key(ecc(curve%s)(flags djb-tweak)(q%m)))":
+                                   "(public-key(ecc(curve%s)(q%m)))",
                                    curve, pk->pkey[1]);
             xfree (curve);
           }
diff --git a/g10/keylist.c b/g10/keylist.c
index d81e7dd..b43165f 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1091,7 +1091,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr,
               || pk2->pubkey_algo == PUBKEY_ALGO_ECDH)
             {
               char *curve = openpgp_oid_to_str (pk2->pkey[0]);
-              const char *name = openpgp_oid_to_curve (curve);
+              const char *name = openpgp_oid_to_curve (curve, 0);
               if (!name)
                 name = curve;
               es_fprintf (es_stdout, " %s", name);
@@ -1358,7 +1358,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
       || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
     {
       char *curve = openpgp_oid_to_str (pk->pkey[0]);
-      const char *name = openpgp_oid_to_curve (curve);
+      const char *name = openpgp_oid_to_curve (curve, 0);
       if (!name)
         name = curve;
       es_fputs (name, es_stdout);
@@ -1487,7 +1487,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr)
               || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
             {
               char *curve = openpgp_oid_to_str (pk->pkey[0]);
-              const char *name = openpgp_oid_to_curve (curve);
+              const char *name = openpgp_oid_to_curve (curve, 0);
               if (!name)
                 name = curve;
               es_fputs (name, es_stdout);
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 6131d32..478612a 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -2086,7 +2086,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
                    || algorithm == PUBKEY_ALGO_ECDH) && i==0)
                 {
                   char *curve = openpgp_oid_to_str (pk->pkey[0]);
-                  const char *name = openpgp_oid_to_curve (curve);
+                  const char *name = openpgp_oid_to_curve (curve, 0);
                   es_fprintf (listfp, " %s (%s)", name?name:"", curve);
                   xfree (curve);
                 }
diff --git a/g10/pkglue.c b/g10/pkglue.c
index d72275b..a8b92f6 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -228,9 +228,13 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data,
             rc = gpg_error_from_syserror ();
           else
             {
+              int with_djb_tweak_flag = openpgp_oid_is_curve25519 (pkey[0]);
+
               /* Now use the ephemeral secret to compute the shared point.  */
               rc = gcry_sexp_build (&s_pkey, NULL,
-                                    "(public-key(ecdh(curve%s)(q%m)))",
+                                    with_djb_tweak_flag ?
+                                    "(public-key(ecdh(curve%s)(flags djb-tweak)(q%m)))"
+                                    : "(public-key(ecdh(curve%s)(q%m)))",
                                     curve, pkey[1]);
               xfree (curve);
               /* Put K into a simplified S-expression.  */
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index cb834af..fd7f812 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -250,8 +250,8 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
       if(err)
         goto leave;

-      /* Reuse NFRAME, which size is sufficient to include the session key.  */
-      err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
+      xfree (frame);
+      err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded);
       mpi_release (decoded);
       if (err)
         goto leave;
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 83465f4..dd9e3c8 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -235,7 +235,7 @@ struct app_local_s {
    } keyattr[3];
 };

-#define ECC_FLAG_EDDSA (1 << 0)
+#define ECC_FLAG_DJB_TWEAK (1 << 0)


 /***** Local prototypes  *****/
@@ -909,9 +909,10 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int keyno)
     {
       snprintf (buffer, sizeof buffer, "%d %d %s",
                 keyno+1,
-                app->app_local->keyattr[keyno].ecc.flags? PUBKEY_ALGO_EDDSA:
-                (keyno==1? PUBKEY_ALGO_ECDH: PUBKEY_ALGO_ECDSA),
-                openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid));
+                keyno==1? PUBKEY_ALGO_ECDH :
+                app->app_local->keyattr[keyno].ecc.flags?
+                PUBKEY_ALGO_EDDSA : PUBKEY_ALGO_ECDSA,
+                openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 0));
     }
   else
     snprintf (buffer, sizeof buffer, "%d 0 0 UNKNOWN", keyno+1);
@@ -1378,59 +1379,52 @@ get_public_key (app_t app, int keyno)
 	}
     }

-
-  mbuf = xtrymalloc ( mlen + 1);
+  mbuf = xtrymalloc (mlen + 1);
   if (!mbuf)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
-  /* Prepend numbers with a 0 if needed.  */
+
   if ((app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA
        || (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC
            && !app->app_local->keyattr[keyno].ecc.flags))
       && mlen && (*m & 0x80))
-    {
+    {               /* Prepend numbers with a 0 if needed for MPI.  */
       *mbuf = 0;
       memcpy (mbuf+1, m, mlen);
       mlen++;
     }
-  else
-    memcpy (mbuf, m, mlen);
-
-  ebuf = xtrymalloc ( elen + 1);
-  if (!ebuf)
-    {
-      err = gpg_error_from_syserror ();
-      goto leave;
-    }
-  /* Prepend numbers with a 0 if needed.  */
-  if (elen && (*e & 0x80))
-    {
-      *ebuf = 0;
-      memcpy (ebuf+1, e, elen);
-      elen++;
+  else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC
+           && app->app_local->keyattr[keyno].ecc.flags)
+    {               /* Prepend 0x40 prefix.  */
+      *mbuf = 0x40;
+      memcpy (mbuf+1, m, mlen);
+      mlen++;
     }
   else
-    memcpy (ebuf, e, elen);
+    memcpy (mbuf, m, mlen);

   if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
     {
-      err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
-                             (int)mlen, mbuf, (int)elen, ebuf);
-      if (err)
-        goto leave;
-
-      len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
-      keybuf = xtrymalloc (len);
-      if (!keybuf)
+      ebuf = xtrymalloc (elen + 1);
+      if (!ebuf)
         {
-          gcry_sexp_release (s_pkey);
           err = gpg_error_from_syserror ();
           goto leave;
         }
-      gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
-      gcry_sexp_release (s_pkey);
+      /* Prepend numbers with a 0 if needed.  */
+      if (elen && (*e & 0x80))
+        {
+          *ebuf = 0;
+          memcpy (ebuf+1, e, elen);
+          elen++;
+        }
+      else
+        memcpy (ebuf, e, elen);
+
+      err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
+                             (int)mlen, mbuf, (int)elen, ebuf);
     }
   else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
     {
@@ -1438,32 +1432,32 @@ get_public_key (app_t app, int keyno)

       if (!app->app_local->keyattr[keyno].ecc.flags)
         format = "(public-key(ecc(curve%s)(q%b)))";
+      else if (keyno == 1)
+        format = "(public-key(ecc(curve%s)(flags djb-tweak)(q%b)))";
       else
         format = "(public-key(ecc(curve%s)(flags eddsa)(q%b)))";

       err = gcry_sexp_build (&s_pkey, NULL, format,
-                 openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid),
+               openpgp_oid_to_curve (app->app_local->keyattr[keyno].ecc.oid, 1),
                              (int)mlen, mbuf);
-      if (err)
-        goto leave;
-
-      len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
-
-      keybuf = xtrymalloc (len);
-      if (!keybuf)
-        {
-          gcry_sexp_release (s_pkey);
-          err = gpg_error_from_syserror ();
-          goto leave;
-        }
-      gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
-      gcry_sexp_release (s_pkey);
     }
   else
+    err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+  if (err)
+    goto leave;
+
+  len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
+
+  keybuf = xtrymalloc (len);
+  if (!keybuf)
     {
-      err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+      gcry_sexp_release (s_pkey);
+      err = gpg_error_from_syserror ();
       goto leave;
     }
+  gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keybuf, len);
+  gcry_sexp_release (s_pkey);

   app->app_local->pk[keyno].key = (unsigned char*)keybuf;
   app->app_local->pk[keyno].keylen = len - 1; /* Decrement for trailing '\0' */
@@ -3171,7 +3165,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
   size_t ecc_q_len, ecc_d_len;
   u32 created_at = 0;
   const char *oidstr = NULL;
-  int flag_eddsa = 0;
+  int flag_djb_tweak = 0;
   int algo;

   /* (private-key(ecc(curve%s)(q%m)(d%m))(created-at%d)):
@@ -3216,8 +3210,12 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
           if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
             goto leave;

-          if (tok && toklen == 5 && !memcmp (tok, "eddsa", 5))
-            flag_eddsa = 1;
+          if (tok)
+            {
+              if ((toklen == 5 && !memcmp (tok, "eddsa", 5))
+                  || (toklen == 9 && !memcmp (tok, "djb-tweak", 9)))
+                flag_djb_tweak = 1;
+            }
         }
       else if (tok && toklen == 1)
         {
@@ -3237,7 +3235,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
             }
           if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
             goto leave;
-          if (tok && buf2 && !flag_eddsa)
+          if (tok && buf2 && !flag_djb_tweak)
             /* It's MPI.  Strip off leading zero bytes and save. */
             for (;toklen && !*tok; toklen--, tok++)
               ;
@@ -3300,7 +3298,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
       err = gpg_error (GPG_ERR_INV_VALUE);
       goto leave;
     }
-  if (flag_eddsa && keyno != 1)
+  if (flag_djb_tweak && keyno != 1)
     algo = PUBKEY_ALGO_EDDSA;
   else if (keyno == 1)
     algo = PUBKEY_ALGO_ECDH;
@@ -3309,7 +3307,7 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),

   if (app->app_local->keyattr[keyno].key_type != KEY_TYPE_ECC
       || app->app_local->keyattr[keyno].ecc.oid != oidstr
-      || app->app_local->keyattr[keyno].ecc.flags != flag_eddsa)
+      || app->app_local->keyattr[keyno].ecc.flags != flag_djb_tweak)
     {
       log_error ("key attribute on card doesn't match\n");
       err = gpg_error (GPG_ERR_INV_VALUE);
@@ -4469,11 +4467,18 @@ parse_algorithm_attribute (app_t app, int keyno)
         {
           app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC;
           app->app_local->keyattr[keyno].ecc.oid = oid;
-          app->app_local->keyattr[keyno].ecc.flags = (*buffer == PUBKEY_ALGO_EDDSA);
+          if (*buffer == PUBKEY_ALGO_EDDSA
+              || (*buffer == PUBKEY_ALGO_ECDH
+                  && !strcmp (app->app_local->keyattr[keyno].ecc.oid,
+                              "1.3.6.1.4.1.3029.1.5.1")))
+            app->app_local->keyattr[keyno].ecc.flags = ECC_FLAG_DJB_TWEAK;
+          else
+            app->app_local->keyattr[keyno].ecc.flags = 0;
           if (opt.verbose)
             log_printf
               ("ECC, curve=%s%s\n", app->app_local->keyattr[keyno].ecc.oid,
-               app->app_local->keyattr[keyno].ecc.flags ? " (eddsa)": "");
+               !app->app_local->keyattr[keyno].ecc.flags ? "":
+               keyno==1? " (djb-tweak)": " (eddsa)");
         }
     }
   else if (opt.verbose)
--



More information about the Gnupg-devel mailing list