[git] GnuPG - branch, master, updated. gnupg-2.1.15-241-g34439da

by NIIBE Yutaka cvs at cvs.gnupg.org
Tue Oct 18 16:02:27 CEST 2016


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 Privacy Guard".

The branch, master has been updated
       via  34439da2d62b964a914ace66bae7e38f619582a4 (commit)
      from  f1845f25dbea79c191427710fa56ed01e63a045b (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 34439da2d62b964a914ace66bae7e38f619582a4
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Oct 18 22:46:37 2016 +0900

    scd: Support ECC key generation.
    
    * scd/app-openpgp.c (get_public_key): Fix a message.
    (change_keyattr_from_string, ecc_writekey): Call mpi_release sooner.
    (do_genkey): Add ECC support.
    
    --
    
    In OpenPGP card specification 3.0, ECC is introduced.  So far, do_genkey
    only supported RSA.  Since KDF spec. is needed to calculate the
    fingerprint, it is hard coded in app-openpgp.c.  But it's defined by
    OpenPGP ECC (RFC-6637), and card does nothing with KDF in fact.
    
    Co-authored-by: Arnaud Fontaine <arnaud.fontaine at ssi.gouv.fr>
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index ba16255..09e4800 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1318,7 +1318,7 @@ get_public_key (app_t app, int keyno)
           if (!m)
             {
               err = gpg_error (GPG_ERR_CARD);
-              log_error (_("response does not contain the EC public point\n"));
+              log_error (_("response does not contain the EC public key\n"));
               goto leave;
             }
         }
@@ -2847,6 +2847,7 @@ change_keyattr_from_string (app_t app,
       size_t oid_len;
 
       oidstr = openpgp_curve_to_oid (string+n, NULL);
+      gcry_mpi_release (oid);
       if (!oidstr)
         {
           err = gpg_error (GPG_ERR_INV_DATA);
@@ -2864,7 +2865,6 @@ change_keyattr_from_string (app_t app,
       string[0] = algo;
       memcpy (string+1, oidbuf+1, oid_len-1);
       err = change_keyattr (app, keyno, string, oid_len, pincb, pincb_arg);
-      gcry_mpi_release (oid);
     }
   else
     err = gpg_error (GPG_ERR_PUBKEY_ALGO);
@@ -3355,13 +3355,14 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
   if (err)
     goto leave;
   oidbuf = gcry_mpi_get_opaque (oid, &n);
-  oid_len = (n+7)/8;
   if (!oidbuf)
     {
       err = gpg_error_from_syserror ();
       gcry_mpi_release (oid);
       goto leave;
     }
+  gcry_mpi_release (oid);
+  oid_len = (n+7)/8;
 
   if (app->app_local->keyattr[keyno].key_type != KEY_TYPE_ECC
       || app->app_local->keyattr[keyno].ecc.oid != oidstr
@@ -3442,8 +3443,6 @@ ecc_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **),
                    ecc_q, ecc_q_len, "\x03\x01\x08\x07", (size_t)4);
 
  leave:
-  if (oidbuf)
-    gcry_mpi_release (oid);
   return err;
 }
 
@@ -3535,16 +3534,15 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   gpg_error_t err;
   char numbuf[30];
   unsigned char fprbuf[20];
-  const unsigned char *keydata, *m, *e;
   unsigned char *buffer = NULL;
-  size_t buflen, keydatalen, mlen, elen;
+  const unsigned char *keydata;
+  size_t buflen, keydatalen;
   u32 created_at;
   int keyno = atoi (keynostr) - 1;
   int force = (flags & 1);
   time_t start_at;
-  int exmode;
-  int le_value;
-  unsigned int keybits;
+  int exmode = 0;
+  int le_value = 256; /* Use legacy value. */
 
   if (keyno < 0 || keyno > 2)
     return gpg_error (GPG_ERR_INV_ID);
@@ -3564,34 +3562,34 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   if (err)
     return err;
 
-  /* Because we send the key parameter back via status lines we need
-     to put a limit on the max. allowed keysize.  2048 bit will
-     already lead to a 527 byte long status line and thus a 4096 bit
-     key would exceed the Assuan line length limit.  */
-  keybits = app->app_local->keyattr[keyno].rsa.n_bits;
-  if (keybits > 4096)
-    return gpg_error (GPG_ERR_TOO_LARGE);
+  if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
+    {
+      unsigned int keybits = app->app_local->keyattr[keyno].rsa.n_bits;
+
+      /* Because we send the key parameter back via status lines we need
+         to put a limit on the max. allowed keysize.  2048 bit will
+         already lead to a 527 byte long status line and thus a 4096 bit
+         key would exceed the Assuan line length limit.  */
+      if (keybits > 4096)
+        return gpg_error (GPG_ERR_TOO_LARGE);
+
+      /* Test whether we will need extended length mode.  (1900 is an
+         arbitrary length which for sure fits into a short apdu.)  */
+      if (app->app_local->cardcap.ext_lc_le && keybits > 1900)
+        {
+          exmode = 1;    /* Use extended length w/o a limit.  */
+          le_value = app->app_local->extcap.max_rsp_data;
+          /* No need to check le_value because it comes from a 16 bit
+             value and thus can't create an overflow on a 32 bit
+             system.  */
+        }
+    }
 
   /* Prepare for key generation by verifying the Admin PIN.  */
   err = verify_chv3 (app, pincb, pincb_arg);
   if (err)
-    goto leave;
+    return err;
 
-  /* Test whether we will need extended length mode.  (1900 is an
-     arbitrary length which for sure fits into a short apdu.)  */
-  if (app->app_local->cardcap.ext_lc_le && keybits > 1900)
-    {
-      exmode = 1;    /* Use extended length w/o a limit.  */
-      le_value = app->app_local->extcap.max_rsp_data;
-      /* No need to check le_value because it comes from a 16 bit
-         value and thus can't create an overflow on a 32 bit
-         system.  */
-    }
-  else
-    {
-      exmode = 0;
-      le_value = 256; /* Use legacy value. */
-    }
 
   log_info (_("please wait while key is being generated ...\n"));
   start_at = time (NULL);
@@ -3601,9 +3599,8 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
                                   2, le_value, &buffer, &buflen);
   if (err)
     {
-      err = gpg_error (GPG_ERR_CARD);
       log_error (_("generating key failed\n"));
-      goto leave;
+      return gpg_error (GPG_ERR_CARD);
     }
 
   {
@@ -3621,38 +3618,117 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
       goto leave;
     }
 
-  m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
-  if (!m)
-    {
-      err = gpg_error (GPG_ERR_CARD);
-      log_error (_("response does not contain the RSA modulus\n"));
-      goto leave;
-    }
-  /* log_printhex ("RSA n:", m, mlen); */
-  send_key_data (ctrl, "n", m, mlen);
-
-  e = find_tlv (keydata, keydatalen, 0x0082, &elen);
-  if (!e)
-    {
-      err = gpg_error (GPG_ERR_CARD);
-      log_error (_("response does not contain the RSA public exponent\n"));
-      goto leave;
-    }
-  /* log_printhex ("RSA e:", e, elen); */
-  send_key_data (ctrl, "e", e, elen);
-
   created_at = (u32)(createtime? createtime : gnupg_get_time ());
   sprintf (numbuf, "%u", created_at);
   send_status_info (ctrl, "KEY-CREATED-AT",
                     numbuf, (size_t)strlen(numbuf), NULL, 0);
 
-  for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
-    ;
-  for (; elen && !*e; elen--, e++) /* strip leading zeroes */
-    ;
+  if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
+    {
+      const unsigned char *m, *e;
+      size_t mlen, elen;
+
+      m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
+      if (!m)
+        {
+          err = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the RSA modulus\n"));
+          goto leave;
+        }
+      /* log_printhex ("RSA n:", m, mlen); */
+      send_key_data (ctrl, "n", m, mlen);
+
+      e = find_tlv (keydata, keydatalen, 0x0082, &elen);
+      if (!e)
+        {
+          err = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the RSA public exponent\n"));
+          goto leave;
+        }
+      /* log_printhex ("RSA e:", e, elen); */
+      send_key_data (ctrl, "e", e, elen);
+
+      for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
+        ;
+      for (; elen && !*e; elen--, e++) /* strip leading zeroes */
+        ;
+
+      err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
+                       m, mlen, e, elen);
+    }
+  else if (app->app_local->keyattr[keyno].key_type == KEY_TYPE_ECC)
+    {
+      const unsigned char *ecc_q;
+      size_t ecc_q_len;
+      gcry_mpi_t oid;
+      int n;
+      const unsigned char *oidbuf;
+      size_t oid_len;
+      int algo;
+
+      ecc_q = find_tlv (keydata, keydatalen, 0x0086, &ecc_q_len);
+      if (!ecc_q)
+        {
+          err = gpg_error (GPG_ERR_CARD);
+          log_error (_("response does not contain the EC public key\n"));
+          goto leave;
+        }
+
+      err = openpgp_oid_from_str (app->app_local->keyattr[keyno].ecc.oid, &oid);
+      if (err)
+        goto leave;
+
+      oidbuf = gcry_mpi_get_opaque (oid, &n);
+      if (!oidbuf)
+        {
+          err = gpg_error_from_syserror ();
+          gcry_mpi_release (oid);
+          goto leave;
+        }
+      gcry_mpi_release (oid);
+      oid_len = (n+7)/8;
+
+      if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
+        {               /* Prepend 0x40 prefix.  */
+          unsigned char *q = xtrymalloc (ecc_q_len + 1);
+
+          if (!q)
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          *q = 0x40;
+          memcpy (q+1, ecc_q, ecc_q_len);
+          send_key_data (ctrl, "q", q, ecc_q_len + 1);
+          xfree (q);
+        }
+      else
+        {
+          /* strip leading zeroes */
+          for (; ecc_q_len && !*ecc_q; ecc_q_len--, ecc_q++)
+            ;
+          send_key_data (ctrl, "q", ecc_q, ecc_q_len);
+        }
+
+      send_key_data (ctrl, "curve", oidbuf, oid_len);
+
+      if (keyno == 1)
+        {
+          send_key_data (ctrl, "kdf", "\x03\x01\x08\x07", (size_t)4);
+          algo = PUBKEY_ALGO_ECDH;
+        }
+      else
+        {
+          if ((app->app_local->keyattr[keyno].ecc.flags & ECC_FLAG_DJB_TWEAK))
+            algo = PUBKEY_ALGO_EDDSA;
+          else
+            algo = PUBKEY_ALGO_ECDSA;
+        }
+
+      err = store_fpr (app, keyno, created_at, fprbuf, algo, oidbuf, oid_len,
+                       ecc_q, ecc_q_len, "\x03\x01\x08\x07", (size_t)4);
+    }
 
-  err = store_fpr (app, keyno, created_at, fprbuf, PUBKEY_ALGO_RSA,
-                   m, mlen, e, elen);
   if (err)
     goto leave;
   send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);

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

Summary of changes:
 scd/app-openpgp.c | 198 +++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 137 insertions(+), 61 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list