[git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.30-28-g5c599e4

by NIIBE Yutaka cvs at cvs.gnupg.org
Wed Nov 30 02:18:51 CET 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, STABLE-BRANCH-2-0 has been updated
       via  5c599e4f6edd288f4759c9fc2bcf9fe87dee1836 (commit)
       via  bb5a153f9dd9497f58935c2a7026220f3a99cffd (commit)
       via  3089c76a4a6a4250489a8ea373e5810bc9593654 (commit)
       via  354f8119bc24c93b3ead367af7ded8dd271feb3c (commit)
       via  88556386a61f5fa9ce8c5abbe1fd6d66a7723854 (commit)
       via  68d3e461f67404d1b47dfa7b9efdb6ac2c087bb7 (commit)
       via  710d0ce0fd5ee33b1e57f1ae9aedb90c7f7e234d (commit)
       via  5acce7060ca48e6c5e06a3918950c4eb83668fda (commit)
       via  519c01a0fd6cfc9d4282251e187d45194325c85b (commit)
       via  3b3386a3fd973ed7f388b1356138941c302848f2 (commit)
       via  f916d5756fae163896715b057a627a5fb58ddd52 (commit)
       via  51464a0eadc82c84780fba08a53163cb6e4da2a4 (commit)
       via  d87699597f4b47968902324c90beb3f3c51ff1d7 (commit)
       via  d4316d13749bd8662525c2b7c416d39c5d4d8089 (commit)
       via  af7245e9a79d11866aa9c40f8f53291f82dd74b5 (commit)
       via  a6f7c8d9b70daba319d24d930be056618cbad61b (commit)
       via  f1b9521fd6bd46547090efb1de78fa46bf2abfd2 (commit)
      from  cbd0308bc70855a2dd34bda85b9b40a61199678c (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 5c599e4f6edd288f4759c9fc2bcf9fe87dee1836
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Nov 25 16:12:26 2016 +0900

    scd: Support OpenPGP card V3 for RSA.
    
    * scd/app-openpgp.c (struct app_local_s): Remove max_cmd_data and
    max_rsp_data fields as Extended Capabilities bits are different.
    (get_cached_data) Use extcap.max_certlen_3.
    (get_one_do): Don't use exmode=1.
    (determine_rsa_response): New.
    (get_public_key, do_genkey): Call determine_rsa_response.
    (do_sign): Use keyattr[0].rsa.n_bits / 8, instead of max_rsp_data.
    (do_auth): Use keyattr[2].rsa.n_bits / 8, instead of max_rsp_data.
    (do_decipher): Likewise with Use keyattr[1].rsa.n_bits / 8.
    (show_caps): Remove max_cmd_data and max_rsp_data.
    (app_select_openpgp): Likewise.
    
    --
    Backport of master commit: b89e63e5c326af71470124b410e6429cbd2b5c43
    
    OpenPGP card V3 had introduced incompatible change in Extended
    Capabilities bits.  We can work around by this change by not
    using those bits.
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 972362c..5983aba 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -182,8 +182,6 @@ struct app_local_s {
     unsigned int sm_aes128:1;          /* Use AES-128 for SM.  */
     unsigned int max_certlen_3:16;
     unsigned int max_get_challenge:16; /* Maximum size for get_challenge.  */
-    unsigned int max_cmd_data:16;      /* Maximum data size for a command.  */
-    unsigned int max_rsp_data:16;      /* Maximum size of a response.  */
   } extcap;
 
   /* Flags used to control the application.  */
@@ -300,7 +298,7 @@ get_cached_data (app_t app, int tag,
     }
 
   if (try_extlen && app->app_local->cardcap.ext_lc_le)
-    exmode = app->app_local->extcap.max_rsp_data;
+    exmode = app->app_local->extcap.max_certlen_3;
   else
     exmode = 0;
 
@@ -430,10 +428,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
 
   if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
     {
-      if (data_objects[i].try_extlen && app->app_local->cardcap.ext_lc_le)
-        exmode = app->app_local->extcap.max_rsp_data;
-      else
-        exmode = 0;
+      exmode = 0;
       rc = iso7816_get_data (app->slot, exmode, tag, &buffer, &buflen);
       if (rc)
         {
@@ -865,6 +860,22 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
 }
 
 
+#define RSA_SMALL_SIZE_KEY 1952
+#define RSA_SMALL_SIZE_OP  2048
+
+static int
+determine_rsa_response (app_t app, int keyno)
+{
+  int size;
+
+  size = 2 + 3 /* header */
+    + 4 /* tag+len */ + app->app_local->keyattr[keyno].n_bits/8
+    + 2 /* tag+len */ + app->app_local->keyattr[keyno].e_bits/8;
+
+  return size;
+}
+
+
 /* Implement the GETATTR command.  This is similar to the LEARN
    command but returns just one value via the status interface. */
 static gpg_error_t
@@ -1199,10 +1210,11 @@ get_public_key (app_t app, int keyno)
       int exmode, le_value;
 
       /* We may simply read the public key out of these cards.  */
-      if (app->app_local->cardcap.ext_lc_le)
+      if (app->app_local->cardcap.ext_lc_le
+          && app->app_local->keyattr[keyno].n_bits > RSA_SMALL_SIZE_KEY)
         {
           exmode = 1;    /* Use extended length.  */
-          le_value = app->app_local->extcap.max_rsp_data;
+          le_value = determine_rsa_response (app, keyno);
         }
       else
         {
@@ -3042,12 +3054,11 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   if (err)
     goto leave;
 
-  /* 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)
+  /* Test whether we will need extended length mode.  */
+  if (app->app_local->cardcap.ext_lc_le && keybits > RSA_SMALL_SIZE_KEY)
     {
       exmode = 1;    /* Use extended length w/o a limit.  */
-      le_value = app->app_local->extcap.max_rsp_data;
+      le_value = determine_rsa_response (app, keyno);
       /* 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.  */
@@ -3406,10 +3417,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
     }
 
 
-  if (app->app_local->cardcap.ext_lc_le)
+  if (app->app_local->cardcap.ext_lc_le
+      && app->app_local->keyattr[0].n_bits > RSA_SMALL_SIZE_OP)
     {
       exmode = 1;    /* Use extended length.  */
-      le_value = app->app_local->extcap.max_rsp_data;
+      le_value = app->app_local->keyattr[0].n_bits / 8;
     }
   else
     {
@@ -3491,10 +3503,11 @@ do_auth (app_t app, const char *keyidstr,
     {
       int exmode, le_value;
 
-      if (app->app_local->cardcap.ext_lc_le)
+      if (app->app_local->cardcap.ext_lc_le
+          && app->app_local->keyattr[2].n_bits > RSA_SMALL_SIZE_OP)
         {
           exmode = 1;    /* Use extended length.  */
-          le_value = app->app_local->extcap.max_rsp_data;
+          le_value = app->app_local->keyattr[2].n_bits / 8;
         }
       else
         {
@@ -3607,10 +3620,12 @@ do_decipher (app_t app, const char *keyidstr,
           padind = -1; /* Already padded.  */
         }
 
-      if (app->app_local->cardcap.ext_lc_le && indatalen > 254 )
+      if (app->app_local->cardcap.ext_lc_le
+          && (indatalen > 254
+              || app->app_local->keyattr[1].n_bits > RSA_SMALL_SIZE_OP))
         {
           exmode = 1;    /* Extended length w/o a limit.  */
-          le_value = app->app_local->extcap.max_rsp_data;
+          le_value = app->app_local->keyattr[1].n_bits / 8;
         }
       else if (app->app_local->cardcap.cmd_chaining && indatalen > 254)
         {
@@ -3742,8 +3757,6 @@ show_caps (struct app_local_s *s)
   if (s->extcap.sm_supported)
     log_printf (" (%s)", s->extcap.sm_aes128? "AES-128":"3DES");
   log_info ("Max-Cert3-Len ..: %u\n", s->extcap.max_certlen_3);
-  log_info ("Max-Cmd-Data ...: %u\n", s->extcap.max_cmd_data);
-  log_info ("Max-Rsp-Data ...: %u\n", s->extcap.max_rsp_data);
   log_info ("Cmd-Chaining ...: %s\n", s->cardcap.cmd_chaining?"yes":"no");
   log_info ("Ext-Lc-Le ......: %s\n", s->cardcap.ext_lc_le?"yes":"no");
   log_info ("Status Indicator: %02X\n", s->status_indicator);
@@ -3971,8 +3984,6 @@ app_select_openpgp (app_t app)
           app->app_local->extcap.max_get_challenge
                                                = (buffer[2] << 8 | buffer[3]);
           app->app_local->extcap.max_certlen_3 = (buffer[4] << 8 | buffer[5]);
-          app->app_local->extcap.max_cmd_data  = (buffer[6] << 8 | buffer[7]);
-          app->app_local->extcap.max_rsp_data  = (buffer[8] << 8 | buffer[9]);
         }
       xfree (relptr);
 

commit bb5a153f9dd9497f58935c2a7026220f3a99cffd
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Nov 22 20:53:57 2016 +0900

    scd: Fix receive buffer size.
    
    * scd/apdu.c (send_le): Fix the size, adding two for status
    bytes to Le.
    
    --
    Backport of master commit: 5c2db9dedfe9dbb14ffec24751ca23a69cead94e
    
    This is long standing bug.  So far, Le was not exact value.
    Since forthcoming change will introduce exact value of expected length
    of response data, this change is needed.
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/apdu.c b/scd/apdu.c
index 0beee25..97bce79 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -3648,8 +3648,9 @@ send_le (int slot, int class, int ins, int p0, int p1,
 
   if (use_extended_length && (le > 256 || le < 0))
     {
-      result_buffer_size = le < 0? 4096 : le;
-      result_buffer = xtrymalloc (result_buffer_size + 10);
+      /* Two more bytes are needed for status bytes.  */
+      result_buffer_size = le < 0? 4096 : (le + 2);
+      result_buffer = xtrymalloc (result_buffer_size);
       if (!result_buffer)
         {
           xfree (apdu_buffer);

commit 3089c76a4a6a4250489a8ea373e5810bc9593654
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Nov 18 08:54:04 2016 +0900

    scd: Don't limit to ST-2xxx for PC/SC.
    
    * scd/apdu.c (pcsc_vendor_specific_init): Only check vender ID.
    
    --
    Backport of master commit: b6066ab18a67195817babaf9eccf896c2b3c7b0e
    
    Some other products by Cherry works with pinpad, although it only works
    for smaller keys (RSA 1024).  TPDU support is good for larger keys.
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/apdu.c b/scd/apdu.c
index 570e150..0beee25 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -1855,8 +1855,12 @@ pcsc_vendor_specific_init (int slot)
       reader_table[slot].is_spr532 = 1;
       reader_table[slot].pinpad_varlen_supported = 1;
     }
-  else if (vendor == 0x046a && product == 0x003e) /* Cherry ST-2xxx */
+  else if (vendor == 0x046a)
     {
+      /* Cherry ST-2xxx (product == 0x003e) supports TPDU level
+       * exchange.  Other products which only support short APDU level
+       * exchange only work with shorter keys like RSA 1024.
+       */
       reader_table[slot].pcsc.pinmax = 15;
       reader_table[slot].pinpad_varlen_supported = 1;
     }

commit 354f8119bc24c93b3ead367af7ded8dd271feb3c
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Nov 14 10:25:43 2016 +0900

    scd: Fix status info encoding.
    
    * scd/command.c (send_status_info): Do percent plus encoding correctly.
    
    --
    Backport of master commit: 4ee4d0b02172cf56d9582bb99e32a65c75315b25
    
    Reported-by: David Härdeman <david at hardeman.nu>
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/command.c b/scd/command.c
index 963cb3e..2c43a3a 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -2103,7 +2103,8 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
         }
       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
         {
-          if (*value < ' ' || *value == '+')
+          if (*value == '+' || *value == '\"' || *value == '%'
+              || *value < ' ')
             {
               sprintf (p, "%%%02X", *value);
               p += 3;

commit 88556386a61f5fa9ce8c5abbe1fd6d66a7723854
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Oct 18 20:40:09 2016 +0900

    scd: minor cleanup to merge other works.
    
    * scd/iso7816.c (do_generate_keypair): Use const char * for DATA.
    (iso7816_generate_keypair, iso7816_read_public_key): Likewise.
    * scd/app-openpgp.c (get_public_key): Follow the change.
    (do_genkey): Ditto.  Use ERR instead of RC.  Use u32 for CREATED_AT.
    --
    Backport of master commit: f1845f25dbea79c191427710fa56ed01e63a045b
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 59ccd6d..972362c 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1210,12 +1210,10 @@ get_public_key (app_t app, int keyno)
           le_value = 256; /* Use legacy value. */
         }
 
-      err = iso7816_read_public_key
-        (app->slot, exmode,
-         (const unsigned char*)(keyno == 0? "\xB6" :
-                                keyno == 1? "\xB8" : "\xA4"), 2,
-         le_value,
-         &buffer, &buflen);
+      err = iso7816_read_public_key (app->slot, exmode,
+                                     (keyno == 0? "\xB6" :
+                                      keyno == 1? "\xB8" : "\xA4"),
+                                     2, le_value, &buffer, &buflen);
       if (err)
         {
           log_error (_("reading public key failed: %s\n"), gpg_strerror (err));
@@ -2999,13 +2997,13 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
            gpg_error_t (*pincb)(void*, const char *, char **),
            void *pincb_arg)
 {
-  int rc;
+  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;
-  time_t created_at;
+  u32 created_at;
   int keyno = atoi (keynostr) - 1;
   int force = (flags & 1);
   time_t start_at;
@@ -3027,9 +3025,9 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   app->app_local->pk[keyno].read_done = 0;
 
   /* Check whether a key already exists.  */
-  rc = does_key_exist (app, keyno, 1, force);
-  if (rc)
-    return rc;
+  err = does_key_exist (app, keyno, 1, force);
+  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
@@ -3040,8 +3038,8 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
     return gpg_error (GPG_ERR_TOO_LARGE);
 
   /* Prepare for key generation by verifying the Admin PIN.  */
-  rc = verify_chv3 (app, pincb, pincb_arg);
-  if (rc)
+  err = verify_chv3 (app, pincb, pincb_arg);
+  if (err)
     goto leave;
 
   /* Test whether we will need extended length mode.  (1900 is an
@@ -3062,17 +3060,13 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
 
   log_info (_("please wait while key is being generated ...\n"));
   start_at = time (NULL);
-  rc = iso7816_generate_keypair
-/* # warning key generation temporary replaced by reading an existing key. */
-/*   rc = iso7816_read_public_key */
-    (app->slot, exmode,
-     (const unsigned char*)(keyno == 0? "\xB6" :
-                            keyno == 1? "\xB8" : "\xA4"), 2,
-     le_value,
-     &buffer, &buflen);
-  if (rc)
+  err = iso7816_generate_keypair (app->slot, exmode,
+                                  (keyno == 0? "\xB6" :
+                                   keyno == 1? "\xB8" : "\xA4"),
+                                  2, le_value, &buffer, &buflen);
+  if (err)
     {
-      rc = gpg_error (GPG_ERR_CARD);
+      err = gpg_error (GPG_ERR_CARD);
       log_error (_("generating key failed\n"));
       goto leave;
     }
@@ -3082,7 +3076,7 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen);
   if (!keydata)
     {
-      rc = gpg_error (GPG_ERR_CARD);
+      err = gpg_error (GPG_ERR_CARD);
       log_error (_("response does not contain the public key data\n"));
       goto leave;
     }
@@ -3090,7 +3084,7 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
   if (!m)
     {
-      rc = gpg_error (GPG_ERR_CARD);
+      err = gpg_error (GPG_ERR_CARD);
       log_error (_("response does not contain the RSA modulus\n"));
       goto leave;
     }
@@ -3100,28 +3094,28 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   e = find_tlv (keydata, keydatalen, 0x0082, &elen);
   if (!e)
     {
-      rc = gpg_error (GPG_ERR_CARD);
+      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 = createtime? createtime : gnupg_get_time ();
-  sprintf (numbuf, "%lu", (unsigned long)created_at);
+  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);
 
-  rc = store_fpr (app, keyno, (u32)created_at,
+  err = store_fpr (app, keyno, (u32)created_at,
                   m, mlen, e, elen, fprbuf, app->card_version);
-  if (rc)
+  if (err)
     goto leave;
   send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf);
 
 
  leave:
   xfree (buffer);
-  return rc;
+  return err;
 }
 
 
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 2a9aa53..f22626f 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -603,9 +603,8 @@ iso7816_internal_authenticate (int slot, int extended_mode,
    returned.  In that case a value of -1 uses a large default
    (e.g. 4096 bytes), a value larger 256 used that value.  */
 static gpg_error_t
-do_generate_keypair (int slot, int extended_mode, int readonly,
-                     const unsigned char *data, size_t datalen,
-                     int le, 
+do_generate_keypair (int slot, int extended_mode, int read_only,
+                     const char *data, size_t datalen, int le,
                      unsigned char **result, size_t *resultlen)
 {
   int sw;
@@ -616,8 +615,8 @@ do_generate_keypair (int slot, int extended_mode, int readonly,
   *resultlen = 0;
 
   sw = apdu_send_le (slot, extended_mode,
-                     0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0,
-                     datalen, (const char*)data,
+                     0x00, CMD_GENERATE_KEYPAIR, read_only? 0x81:0x80, 0,
+                     datalen, data,
                      le >= 0 && le < 256? 256:le,
                      result, resultlen);
   if (sw != SW_SUCCESS)
@@ -635,8 +634,8 @@ do_generate_keypair (int slot, int extended_mode, int readonly,
 
 gpg_error_t
 iso7816_generate_keypair (int slot, int extended_mode,
-                          const unsigned char *data, size_t datalen,
-                          int le, 
+                          const char *data, size_t datalen,
+                          int le,
                           unsigned char **result, size_t *resultlen)
 {
   return do_generate_keypair (slot, extended_mode, 0,
@@ -646,8 +645,8 @@ iso7816_generate_keypair (int slot, int extended_mode,
 
 gpg_error_t
 iso7816_read_public_key (int slot, int extended_mode,
-                         const unsigned char *data, size_t datalen,
-                         int le, 
+                         const char *data, size_t datalen,
+                         int le,
                          unsigned char **result, size_t *resultlen)
 {
   return do_generate_keypair (slot, extended_mode, 1,
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 4354c72..05fea65 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -100,11 +100,11 @@ gpg_error_t iso7816_internal_authenticate (int slot, int extended_mode,
                                    int le,
                                    unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_generate_keypair (int slot, int extended_mode,
-                                    const unsigned char *data, size_t datalen,
+                                    const char *data, size_t datalen,
                                     int le,
                                     unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_read_public_key (int slot, int extended_mode,
-                                    const unsigned char *data, size_t datalen,
+                                    const char *data, size_t datalen,
                                     int le,
                                     unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_get_challenge (int slot,

commit 68d3e461f67404d1b47dfa7b9efdb6ac2c087bb7
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Sat Sep 3 15:27:30 2016 +0900

    scd: Fix an action after card removal.
    
    * scd/command.c (update_card_removed): Call apdu_close_reader here.
    
    --
    Backport of master commit: f9e49c80e706a27d5e30d4b3237ff26367a67130
    
    This is update of the commit 8fe81055762d9c9e6f03fb7853a985c94ef73ac3
    It is better apdu_close_reader is called in update_card_removed.
    
    The commit 1598a4476466822e7e9c757ac471089d3db4b545 introduced a
    regression, it doesn't close the reader after removal of the card, while
    the code before the commit call apdu_close_reader in do_reset.
    So, this fix.
    
    GnuPG-bug-id: 2449
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/command.c b/scd/command.c
index e35579e..963cb3e 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -200,6 +200,7 @@ update_card_removed (int slot, int value)
   if (value)
     {
       log_debug ("Removal of a card: %d\n", slot);
+      apdu_close_reader (slot);
       application_notify_card_reset (slot);
       slot_table[slot].slot = -1;
     }
@@ -2315,10 +2316,7 @@ update_reader_status_file (int set_card_removed_flag)
 
           /* Set the card removed flag for all current sessions.  */
           if (ss->any && ss->status == 0 && set_card_removed_flag)
-	    {
-              apdu_close_reader (ss->slot);
-              update_card_removed (ss->slot, 1);
-	    }
+            update_card_removed (ss->slot, 1);
 
           ss->any = 1;
 

commit 710d0ce0fd5ee33b1e57f1ae9aedb90c7f7e234d
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Sep 2 14:45:26 2016 +0900

    scd: Release the card reader after card removal.
    
    * scd/command.c (update_reader_status_file): Call apdu_close_reader.
    
    --
    Backport of master commit: 8fe81055762d9c9e6f03fb7853a985c94ef73ac3
    
    GnuPG-bug-id: 2651
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/command.c b/scd/command.c
index 451a922..e35579e 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -2315,7 +2315,10 @@ update_reader_status_file (int set_card_removed_flag)
 
           /* Set the card removed flag for all current sessions.  */
           if (ss->any && ss->status == 0 && set_card_removed_flag)
-            update_card_removed (idx, 1);
+	    {
+              apdu_close_reader (ss->slot);
+              update_card_removed (ss->slot, 1);
+	    }
 
           ss->any = 1;
 

commit 5acce7060ca48e6c5e06a3918950c4eb83668fda
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Sep 2 13:58:33 2016 +0900

    scd: Clean up unused shutdown method.
    
    * scd/apdu.c (shutdown_ccid_reader, apdu_shutdown_reader): Remove.
    (reset_ccid_reader): Don't set shutdown_reader.
    * scd/ccid-driver.c (ccid_shutdown_reader): Remove.
    
    --
    Backport of master commit: d1ae7103352fbda2a05f098379cd3043a0ab5566
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/apdu.c b/scd/apdu.c
index 00351c8..570e150 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -98,7 +98,6 @@ struct reader_table_s {
   int (*connect_card)(int);
   int (*disconnect_card)(int);
   int (*close_reader)(int);
-  int (*shutdown_reader)(int);
   int (*reset_reader)(int);
   int (*get_status_reader)(int, unsigned int *);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
@@ -432,7 +431,6 @@ new_reader_slot (void)
   reader_table[reader].connect_card = NULL;
   reader_table[reader].disconnect_card = NULL;
   reader_table[reader].close_reader = NULL;
-  reader_table[reader].shutdown_reader = NULL;
   reader_table[reader].reset_reader = NULL;
   reader_table[reader].get_status_reader = NULL;
   reader_table[reader].send_apdu_reader = NULL;
@@ -2437,14 +2435,6 @@ close_ccid_reader (int slot)
 
 
 static int
-shutdown_ccid_reader (int slot)
-{
-  ccid_shutdown_reader (reader_table[slot].ccid.handle);
-  return 0;
-}
-
-
-static int
 reset_ccid_reader (int slot)
 {
   int err;
@@ -2609,7 +2599,6 @@ open_ccid_reader (const char *portstr)
     }
 
   reader_table[slot].close_reader = close_ccid_reader;
-  reader_table[slot].shutdown_reader = shutdown_ccid_reader;
   reader_table[slot].reset_reader = reset_ccid_reader;
   reader_table[slot].get_status_reader = get_status_ccid;
   reader_table[slot].send_apdu_reader = send_apdu_ccid;
@@ -3178,24 +3167,6 @@ apdu_prepare_exit (void)
 }
 
 
-/* Shutdown a reader; that is basically the same as a close but keeps
-   the handle ready for later use. A apdu_reset_reader or apdu_connect
-   should be used to get it active again. */
-int
-apdu_shutdown_reader (int slot)
-{
-  int sw;
-
-  if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
-    return SW_HOST_NO_DRIVER;
-  sw = apdu_disconnect (slot);
-  if (sw)
-    return sw;
-  if (reader_table[slot].shutdown_reader)
-    return reader_table[slot].shutdown_reader (slot);
-  return SW_HOST_NOT_SUPPORTED;
-}
-
 /* Enumerate all readers and return information on whether this reader
    is in use.  The caller should start with SLOT set to 0 and
    increment it with each call until an error is returned. */
diff --git a/scd/apdu.h b/scd/apdu.h
index 1524f99..ac16ea1 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -92,7 +92,6 @@ int apdu_open_remote_reader (const char *portstr,
                              void *writefnc_value,
                              void (*closefnc) (void *opaque),
                              void *closefnc_value);
-int apdu_shutdown_reader (int slot);
 int apdu_close_reader (int slot);
 void apdu_prepare_exit (void);
 int apdu_enum_reader (int slot, int *used);
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 95f6c02..07e884c 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -1744,79 +1744,6 @@ do_close_reader (ccid_driver_t handle)
 }
 
 
-/* Reset a reader on HANDLE.  This is useful in case a reader has been
-   plugged of and inserted at a different port.  By resetting the
-   handle, the same reader will be get used.  Note, that on error the
-   handle won't get released.
-
-   This does not return an ATR, so ccid_get_atr should be called right
-   after this one.
-*/
-int
-ccid_shutdown_reader (ccid_driver_t handle)
-{
-  int rc = 0;
-  struct usb_device *dev = NULL;
-  usb_dev_handle *idev = NULL;
-  unsigned char *ifcdesc_extra = NULL;
-  size_t ifcdesc_extra_len;
-  int ifc_no, ep_bulk_out, ep_bulk_in, ep_intr;
-
-  if (!handle || !handle->rid)
-    return CCID_DRIVER_ERR_INV_VALUE;
-
-  do_close_reader (handle);
-
-  if (scan_or_find_devices (-1, handle->rid, NULL, &dev,
-                            &ifcdesc_extra, &ifcdesc_extra_len,
-                            &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr,
-                            &idev, NULL) || !idev)
-    {
-      DEBUGOUT_1 ("no CCID reader with ID %s\n", handle->rid);
-      return CCID_DRIVER_ERR_NO_READER;
-    }
-
-  if (idev)
-    {
-      handle->idev = idev;
-      handle->ifc_no = ifc_no;
-      handle->ep_bulk_out = ep_bulk_out;
-      handle->ep_bulk_in = ep_bulk_in;
-      handle->ep_intr = ep_intr;
-
-      if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len))
-        {
-          DEBUGOUT ("device not supported\n");
-          rc = CCID_DRIVER_ERR_NO_READER;
-          goto leave;
-        }
-
-      rc = usb_claim_interface (idev, ifc_no);
-      if (rc)
-        {
-          DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc);
-          rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
-          goto leave;
-        }
-    }
-
- leave:
-  free (ifcdesc_extra);
-  if (rc)
-    {
-      if (handle->idev)
-        usb_close (handle->idev);
-      handle->idev = NULL;
-      if (handle->dev_fd != -1)
-        close (handle->dev_fd);
-      handle->dev_fd = -1;
-    }
-
-  return rc;
-
-}
-
-
 int
 ccid_set_progress_cb (ccid_driver_t handle,
                       void (*cb)(void *, const char *, int, int, int),

commit 519c01a0fd6cfc9d4282251e187d45194325c85b
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Jul 20 11:35:05 2016 +0900

    scd: Fix card removal/reset on multiple contexts.
    
    * scd/app.c (application_notify_card_reset): Add message for debug.
    *scd/command.c (update_card_removed): Call release_application and set
    SLOT -1 here.
    (struct server_local_s): Remove app_ctx_marked_for_release.
    (do_reset): Don't mark release but call release_application here.
    (open_card): Remove app_ctx_marked_for_release handling.
    (update_reader_status_file): Don't set SLOT here, so that it can be
    released the APP by application_notify_card_reset in
    update_card_removed.
    --
    Backport of master commit: 1598a4476466822e7e9c757ac471089d3db4b545
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/app.c b/scd/app.c
index 0f36409..24ed5b0 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -183,8 +183,12 @@ application_notify_card_reset (int slot)
   /* Release the APP, as it's not reusable any more.  */
   if (lock_table[slot].app)
     {
+      if (lock_table[slot].app->ref_count)
+        log_bug ("trying to release active context\n");
+
       deallocate_app (lock_table[slot].app);
       lock_table[slot].app = NULL;
+      log_debug ("application has been released\n");
     }
 
   unlock_reader (slot);
diff --git a/scd/command.c b/scd/command.c
index 24c51c8..451a922 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -118,10 +118,6 @@ struct server_local_s
      continue operation. */
   int card_removed;
 
-  /* Flag indicating that the application context needs to be released
-     at the next opportunity.  */
-  int app_ctx_marked_for_release;
-
   /* A disconnect command has been sent.  */
   int disconnect_allowed;
 
@@ -185,14 +181,28 @@ update_card_removed (int slot, int value)
     return;
 
   for (sl=session_list; sl; sl = sl->next_session)
-    if (sl->ctrl_backlink
-        && sl->ctrl_backlink->reader_slot == slot)
-      {
-        sl->card_removed = value;
-      }
+    {
+      ctrl_t ctrl = sl->ctrl_backlink;
+
+      if (ctrl && ctrl->reader_slot == slot)
+        {
+          sl->card_removed = value;
+          if (value)
+            {
+              struct app_ctx_s *app = ctrl->app_ctx;
+              ctrl->app_ctx = NULL;
+              release_application (app);
+            }
+        }
+    }
+
   /* Let the card application layer know about the removal.  */
   if (value)
-    application_notify_card_reset (slot);
+    {
+      log_debug ("Removal of a card: %d\n", slot);
+      application_notify_card_reset (slot);
+      slot_table[slot].slot = -1;
+    }
 }
 
 
@@ -288,23 +298,31 @@ do_reset (ctrl_t ctrl, int send_reset)
   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
     BUG ();
 
-  /* If there is an active application, release it.  Tell all other
-     sessions using the same application to release the
-     application.  */
+  /* If there is an active application, release it. */
   if (app)
     {
       ctrl->app_ctx = NULL;
       release_application (app);
-      if (send_reset)
+    }
+
+  /* Release the same application which is used by other sessions.  */
+  if (send_reset)
+    {
+      struct server_local_s *sl;
+
+      for (sl=session_list; sl; sl = sl->next_session)
         {
-          struct server_local_s *sl;
+          ctrl_t c = sl->ctrl_backlink;
 
-          for (sl=session_list; sl; sl = sl->next_session)
-            if (sl->ctrl_backlink
-                && sl->ctrl_backlink->reader_slot == slot)
-              {
-                sl->app_ctx_marked_for_release = 1;
-              }
+          if (c && c != ctrl && c->reader_slot == slot)
+            {
+              struct app_ctx_s *app0 = c->app_ctx;
+              if (app0)
+                {
+                  c->app_ctx = NULL;
+                  release_application (app0);
+                }
+            }
         }
     }
 
@@ -444,16 +462,6 @@ open_card (ctrl_t ctrl, const char *apptype)
   if ( IS_LOCKED (ctrl) )
     return gpg_error (GPG_ERR_LOCKED);
 
-  /* If the application has been marked for release do it now.  We
-     can't do it immediately in do_reset because the application may
-     still be in use.  */
-  if (ctrl->server_local->app_ctx_marked_for_release)
-    {
-      ctrl->server_local->app_ctx_marked_for_release = 0;
-      release_application (ctrl->app_ctx);
-      ctrl->app_ctx = NULL;
-    }
-
   /* If we are already initialized for one specific application we
      need to check that the client didn't requested a specific
      application different from the one in use before we continue. */
@@ -2009,10 +2017,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
 
   /* We open the reader right at startup so that the ticker is able to
      update the status file. */
-  if (ctrl->reader_slot == -1)
-    {
-      ctrl->reader_slot = get_reader_slot ();
-    }
+  ctrl->reader_slot = get_reader_slot ();
 
   /* Command processing loop. */
   for (;;)
@@ -2230,9 +2235,7 @@ update_reader_status_file (int set_card_removed_flag)
       if (sw_apdu == SW_HOST_NO_READER)
         {
           /* Most likely the _reader_ has been unplugged.  */
-	  application_notify_card_reset (ss->slot);
 	  apdu_close_reader (ss->slot);
-	  ss->valid = 0;
           status = 0;
           changed = ss->changed;
         }

commit 3b3386a3fd973ed7f388b1356138941c302848f2
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Jul 19 10:53:39 2016 +0900

    scd: Fix race conditions for release_application.
    
    * scd/command.c (do_reset, cmd_restart): Reset app_ctx before calling
    release_application.
    
    --
    Backport of master commit: 0c1fd4e9884ed7c1edd1819762b9e8a77f606ed3
    
    Thanks to Ben Warren for the report.
    
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/command.c b/scd/command.c
index 44f0b21..24c51c8 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -283,6 +283,7 @@ static void
 do_reset (ctrl_t ctrl, int send_reset)
 {
   int slot = ctrl->reader_slot;
+  struct app_ctx_s *app = ctrl->app_ctx;
 
   if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table))))
     BUG ();
@@ -290,10 +291,10 @@ do_reset (ctrl_t ctrl, int send_reset)
   /* If there is an active application, release it.  Tell all other
      sessions using the same application to release the
      application.  */
-  if (ctrl->app_ctx)
+  if (app)
     {
-      release_application (ctrl->app_ctx);
       ctrl->app_ctx = NULL;
+      release_application (app);
       if (send_reset)
         {
           struct server_local_s *sl;
@@ -1744,13 +1745,14 @@ static gpg_error_t
 cmd_restart (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
+  struct app_ctx_s *app = ctrl->app_ctx;
 
   (void)line;
 
-  if (ctrl->app_ctx)
+  if (app)
     {
-      release_application (ctrl->app_ctx);
       ctrl->app_ctx = NULL;
+      release_application (app);
     }
   if (locked_session && ctrl->server_local == locked_session)
     {

commit f916d5756fae163896715b057a627a5fb58ddd52
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Jun 17 08:36:07 2016 +0200

    scd: Make option --homedir work.
    
    * scd/scdaemon.c (opts): Add --homedir.
    --
    Backport of master commit: def512eb67c8a380f3b873cee0f156deef0b6dda
    
    Without that entry the homedir setting won't work.
    
    GnuPG-bug-id: 2386
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index e133ddc..89b4e0e 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -150,6 +150,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
   ARGPARSE_s_n (oEnablePinpadVarlen, "enable-pinpad-varlen",
                 N_("use variable length input for pinpad")),
+  ARGPARSE_s_s (oHomedir,    "homedir",      "@"),
 
   ARGPARSE_end ()
 };

commit 51464a0eadc82c84780fba08a53163cb6e4da2a4
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon May 2 15:56:02 2016 +0900

    scd: More fix of error return path.
    
    * scd/command.c (open_card): Return GPG_ERR_ENODEV on the failure of
    apdu_connect.
    
    --
    Backport of master commit: 6677d8b61446eb5760a30a2488c992d6e895a9ed
    
    GnuPG-bug-id: 2306
    Signed-off-by: NIIBE Yutaka <gniibe at fsij.org>

diff --git a/scd/command.c b/scd/command.c
index b26bd68..44f0b21 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -482,8 +482,8 @@ open_card (ctrl_t ctrl, const char *apptype)
           else if (sw == SW_HOST_CARD_INACTIVE)
             err = gpg_error (GPG_ERR_CARD_RESET);
           else
-            err = gpg_error (GPG_ERR_CARD);
-	}
+            err = gpg_error (GPG_ERR_ENODEV);
+        }
       else
         err = select_application (ctrl, slot, apptype, &ctrl->app_ctx);
     }

commit d87699597f4b47968902324c90beb3f3c51ff1d7
Author: Justus Winter <justus at g10code.com>
Date:   Tue Nov 17 18:05:51 2015 +0100

    scd: Improve error handling.
    
    * scd/app-openpgp.c (get_public_key): Improve error handling.
    --
    Backport master commit: 6a37b45a7f13cf5d2ae7d6c9cd796a4bd197b80d
    
    Found using the Clang Static Analyzer.
    
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 291700f..59ccd6d 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1362,7 +1362,7 @@ get_public_key (app_t app, int keyno)
   xfree (buffer);
   xfree (mbuf);
   xfree (ebuf);
-  return 0;
+  return err;
 }
 #endif /* GNUPG_MAJOR_VERSION > 1 */
 

commit d4316d13749bd8662525c2b7c416d39c5d4d8089
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Nov 4 21:07:49 2015 +0900

    scd: Fix error handling with libusb-compat library.
    
    * scd/ccid-driver.c (bulk_out): Use LIBUSB_ERRNO_NO_SUCH_DEVICE.
    
    --
    
    With libusb-compat library, the error is different than original
    libusb.  (The libusb-compat library is used by Fedora.)
    
    Backport of master commit: 1e94a672efb8bf66f416bc63bf6670e509a21fe5

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 23b992d..95f6c02 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -1878,6 +1878,11 @@ writen (int fd, const void *buf, size_t nbytes)
   return 0;
 }
 
+#if defined(ENXIO) && !defined(LIBUSB_PATH_MAX) && defined(__GNU_LIBRARY__)
+#define LIBUSB_ERRNO_NO_SUCH_DEVICE ENXIO       /* libusb-compat */
+#elif defined(ENODEV)
+#define LIBUSB_ERRNO_NO_SUCH_DEVICE ENODEV      /* Original libusb */
+#endif
 
 /* Write a MSG of length MSGLEN to the designated bulk out endpoint.
    Returns 0 on success. */
@@ -1952,26 +1957,26 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
                            5000 /* ms timeout */);
       if (rc == msglen)
         return 0;
-#ifdef ENODEV
-      if (rc == -(ENODEV))
+#ifdef LIBUSB_ERRNO_NO_SUCH_DEVICE
+      if (rc == -(LIBUSB_ERRNO_NO_SUCH_DEVICE))
         {
           /* The Linux libusb returns a negative error value.  Catch
              the most important one.  */
-          errno = ENODEV;
+          errno = LIBUSB_ERRNO_NO_SUCH_DEVICE;
           rc = -1;
         }
-#endif /*ENODEV*/
+#endif /*LIBUSB_ERRNO_NO_SUCH_DEVICE*/
 
       if (rc == -1)
         {
           DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno));
-#ifdef ENODEV
-          if (errno == ENODEV)
+#ifdef LIBUSB_ERRNO_NO_SUCH_DEVICE
+          if (errno == LIBUSB_ERRNO_NO_SUCH_DEVICE)
             {
               handle->enodev_seen = 1;
               return CCID_DRIVER_ERR_NO_READER;
             }
-#endif /*ENODEV*/
+#endif /*LIBUSB_ERRNO_NO_SUCH_DEVICE*/
         }
       else
         DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc);

commit af7245e9a79d11866aa9c40f8f53291f82dd74b5
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Sep 28 13:41:59 2015 +0900

    scd: Handle error correctly.
    
    * scd/apdu.c (apdu_connect): Initialize variables and check an error
    of apdu_get_status_internal.
    
    --
    Backport from master commit: 6bb7206e357acfd7276a8f1334c0f0c9cc6ed100

diff --git a/scd/apdu.c b/scd/apdu.c
index 30e5ef9..00351c8 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -3216,8 +3216,8 @@ apdu_enum_reader (int slot, int *used)
 int
 apdu_connect (int slot)
 {
-  int sw;
-  unsigned int status;
+  int sw = 0;
+  unsigned int status = 0;
 
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -3234,15 +3234,15 @@ apdu_connect (int slot)
           unlock_slot (slot);
         }
     }
-  else
-    sw = 0;
 
   /* We need to call apdu_get_status_internal, so that the last-status
      machinery gets setup properly even if a card is inserted while
      scdaemon is fired up and apdu_get_status has not yet been called.
      Without that we would force a reset of the card with the next
      call to apdu_get_status.  */
-  apdu_get_status_internal (slot, 1, 1, &status, NULL);
+  if (!sw)
+    sw = apdu_get_status_internal (slot, 1, 1, &status, NULL);
+
   if (sw)
     ;
   else if (!(status & APDU_CARD_PRESENT))

commit a6f7c8d9b70daba319d24d930be056618cbad61b
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Sep 7 13:09:01 2015 +0900

    scd: KEYNO cleanup.
    
    * scd/app-openpgp.c (get_public_key, send_keypair_info, do_readkey)
    (change_keyattr, change_keyattr_from_string, ecc_writekey, do_genkey)
    (compare_fingerprint, check_against_given_fingerprint): KEYNO starts
    from 0.
    
    --
    Backport of master commit: fd689e85423d0d80d725f0315c52d94f0e9766f8

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index cb61df1..291700f 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1162,7 +1162,7 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
    the APP handle.  On error that field gets cleared.  If we already
    know about the public key we will just return.  Note that this does
    not mean a key is available; this is soley indicated by the
-   presence of the app->app_local->pk[KEYNO-1].key field.
+   presence of the app->app_local->pk[KEYNO].key field.
 
    Note that GnuPG 1.x does not need this and it would be too time
    consuming to send it just for the fun of it. However, given that we
@@ -1181,9 +1181,8 @@ get_public_key (app_t app, int keyno)
   char *keybuf = NULL;
   char *keybuf_p;
 
-  if (keyno < 1 || keyno > 3)
+  if (keyno < 0 || keyno > 2)
     return gpg_error (GPG_ERR_INV_ID);
-  keyno--;
 
   /* Already cached? */
   if (app->app_local->pk[keyno].read_done)
@@ -1369,11 +1368,12 @@ get_public_key (app_t app, int keyno)
 
 
 
-/* Send the KEYPAIRINFO back. KEYNO needs to be in the range [1,3].
+/* Send the KEYPAIRINFO back. KEY needs to be in the range [1,3].
    This is used by the LEARN command. */
 static gpg_error_t
-send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
+send_keypair_info (app_t app, ctrl_t ctrl, int key)
 {
+  int keyno = key - 1;
   gpg_error_t err = 0;
   /* Note that GnuPG 1.x does not need this and it would be too time
      consuming to send it just for the fun of it. */
@@ -1386,19 +1386,19 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
   if (err)
     goto leave;
 
-  assert (keyno >= 1 && keyno <= 3);
-  if (!app->app_local->pk[keyno-1].key)
+  assert (keyno >= 0 && keyno <= 2);
+  if (!app->app_local->pk[keyno].key)
     goto leave; /* No such key - ignore. */
 
-  err = keygrip_from_canon_sexp (app->app_local->pk[keyno-1].key,
-                                 app->app_local->pk[keyno-1].keylen,
+  err = keygrip_from_canon_sexp (app->app_local->pk[keyno].key,
+                                 app->app_local->pk[keyno].keylen,
                                  grip);
   if (err)
     goto leave;
 
   bin2hex (grip, 20, gripstr);
 
-  sprintf (idbuf, "OPENPGP.%d", keyno);
+  sprintf (idbuf, "OPENPGP.%d", keyno+1);
   send_status_info (ctrl, "KEYPAIRINFO",
                     gripstr, 40,
                     idbuf, strlen (idbuf),
@@ -1461,11 +1461,11 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
   unsigned char *buf;
 
   if (!strcmp (keyid, "OPENPGP.1"))
-    keyno = 1;
+    keyno = 0;
   else if (!strcmp (keyid, "OPENPGP.2"))
-    keyno = 2;
+    keyno = 1;
   else if (!strcmp (keyid, "OPENPGP.3"))
-    keyno = 3;
+    keyno = 2;
   else
     return gpg_error (GPG_ERR_INV_ID);
 
@@ -1473,10 +1473,10 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
   if (err)
     return err;
 
-  buf = app->app_local->pk[keyno-1].key;
+  buf = app->app_local->pk[keyno].key;
   if (!buf)
     return gpg_error (GPG_ERR_NO_PUBKEY);
-  *pklen = app->app_local->pk[keyno-1].keylen;;
+  *pklen = app->app_local->pk[keyno].keylen;;
   *pk = xtrymalloc (*pklen);
   if (!*pk)
     {
@@ -2610,14 +2610,18 @@ change_keyattr_from_string (app_t app,
      happen.  */
   if (sscanf (string, " --force %d %d %u", &keyno, &algo, &nbits) != 3)
     err = gpg_error (GPG_ERR_INV_DATA);
-  else if (keyno < 1 || keyno > 3)
-    err = gpg_error (GPG_ERR_INV_ID);
-  else if (algo != PUBKEY_ALGO_RSA)
-    err = gpg_error (GPG_ERR_PUBKEY_ALGO);
-  else if (nbits < 1024)
-    err = gpg_error (GPG_ERR_TOO_SHORT);
-  else
-    err = change_keyattr (app, keyno-1, nbits, pincb, pincb_arg);
+  keyno = keyno - 1;
+  if (!err)
+    {
+      if (keyno < 0 || keyno > 2)
+        err = gpg_error (GPG_ERR_INV_ID);
+      else if (algo != PUBKEY_ALGO_RSA)
+        err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+      else if (nbits < 1024)
+        err = gpg_error (GPG_ERR_TOO_SHORT);
+      else
+        err = change_keyattr (app, keyno, nbits, pincb, pincb_arg);
+    }
 
   xfree (string);
   return err;
@@ -3002,16 +3006,15 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   unsigned char *buffer = NULL;
   size_t buflen, keydatalen, mlen, elen;
   time_t created_at;
-  int keyno = atoi (keynostr);
+  int keyno = atoi (keynostr) - 1;
   int force = (flags & 1);
   time_t start_at;
   int exmode;
   int le_value;
   unsigned int keybits;
 
-  if (keyno < 1 || keyno > 3)
+  if (keyno < 0 || keyno > 2)
     return gpg_error (GPG_ERR_INV_ID);
-  keyno--;
 
   /* We flush the cache to increase the traffic before a key
      generation.  This _might_ help a card to gather more entropy. */
@@ -3161,7 +3164,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
   size_t buflen, n;
   int rc, i;
 
-  assert (keyno >= 1 && keyno <= 3);
+  assert (keyno >= 0 && keyno <= 2);
 
   rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0, 0);
   if (rc)
@@ -3176,7 +3179,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
       log_error (_("error reading fingerprint DO\n"));
       return gpg_error (GPG_ERR_GENERAL);
     }
-  fpr += (keyno-1)*20;
+  fpr += keyno*20;
   for (i=0; i < 20; i++)
     if (sha1fpr[i] != fpr[i])
       {
@@ -3195,7 +3198,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
    gpg has not been updated.  If there is no fingerprint we assume
    that this is okay. */
 static gpg_error_t
-check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
+check_against_given_fingerprint (app_t app, const char *fpr, int key)
 {
   unsigned char tmp[20];
   const char *s;
@@ -3212,7 +3215,7 @@ check_against_given_fingerprint (app_t app, const char *fpr, int keyno)
 
   for (s=fpr, n=0; n < 20; s += 2, n++)
         tmp[n] = xtoi_2 (s);
-  return compare_fingerprint (app, keyno, tmp);
+  return compare_fingerprint (app, key-1, tmp);
 }
 
 

commit f1b9521fd6bd46547090efb1de78fa46bf2abfd2
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jul 17 09:34:47 2015 +0900

    scd: Use cipher.h for constants.
    
    * scd/app-openpgp.c: Include cipher.h.
    
    --
    Backport from master commit:f5d356fb5bbbd0e05a753612455253e4bc335266

diff --git a/scd/Makefile.am b/scd/Makefile.am
index e883180..aa370fa 100644
--- a/scd/Makefile.am
+++ b/scd/Makefile.am
@@ -25,7 +25,7 @@ endif
 
 EXTRA_DIST = ChangeLog-2011 scdaemon-w32info.rc
 
-AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common
+AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common -I$(top_srcdir)/include
 
 include $(top_srcdir)/am/cmacros.am
 
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 2e7a9fc..cb61df1 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -66,7 +66,8 @@
 #include "iso7816.h"
 #include "app-common.h"
 #include "tlv.h"
-#include "../include/host2net.h"
+#include "host2net.h"
+#include "cipher.h"
 
 
 /* A table describing the DOs of the card.  */
@@ -854,6 +855,7 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number)
   assert (number >=0 && number < DIM(app->app_local->keyattr));
 
   /* We only support RSA thus the algo identifier is fixed to 1.  */
+  /* Note that PUBKEY_ALGO_RSA == 1 */
   snprintf (buffer, sizeof buffer, "%d 1 %u %u %d",
             number+1,
             app->app_local->keyattr[number].n_bits,
@@ -940,7 +942,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
                 app->app_local->extcap.max_certlen_3,
                 app->app_local->extcap.algo_attr_change,
                 (app->app_local->extcap.sm_supported
-                 ? (app->app_local->extcap.sm_aes128? 7 : 2)
+                 ? (app->app_local->extcap.sm_aes128? CIPHER_ALGO_AES : CIPHER_ALGO_3DES)
                  : 0));
       send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
       return 0;
@@ -2543,7 +2545,7 @@ change_keyattr (app_t app, int keyno, unsigned int nbits,
   relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL);
   if (!relptr)
     return gpg_error (GPG_ERR_CARD);
-  if (buflen < 6 || buffer[0] != 1)
+  if (buflen < 6 || buffer[0] != PUBKEY_ALGO_RSA)
     {
       /* Attriutes too short or not an RSA key.  */
       xfree (relptr);
@@ -2610,8 +2612,8 @@ change_keyattr_from_string (app_t app,
     err = gpg_error (GPG_ERR_INV_DATA);
   else if (keyno < 1 || keyno > 3)
     err = gpg_error (GPG_ERR_INV_ID);
-  else if (algo != 1)
-    err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Not RSA.  */
+  else if (algo != PUBKEY_ALGO_RSA)
+    err = gpg_error (GPG_ERR_PUBKEY_ALGO);
   else if (nbits < 1024)
     err = gpg_error (GPG_ERR_TOO_SHORT);
   else
@@ -3833,7 +3835,7 @@ parse_algorithm_attribute (app_t app, int keyno)
 
   if (opt.verbose)
     log_info ("Key-Attr-%s ..: ", desc[keyno]);
-  if (*buffer == 1 && (buflen == 5 || buflen == 6))
+  if (*buffer == PUBKEY_ALGO_RSA && (buflen == 5 || buflen == 6))
     {
       app->app_local->keyattr[keyno].n_bits = (buffer[1]<<8 | buffer[2]);
       app->app_local->keyattr[keyno].e_bits = (buffer[3]<<8 | buffer[4]);

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

Summary of changes:
 scd/Makefile.am   |   2 +-
 scd/apdu.c        |  50 ++++-----------
 scd/apdu.h        |   1 -
 scd/app-openpgp.c | 188 ++++++++++++++++++++++++++++--------------------------
 scd/app.c         |   4 ++
 scd/ccid-driver.c |  92 ++++----------------------
 scd/command.c     |  97 +++++++++++++++-------------
 scd/iso7816.c     |  17 +++--
 scd/iso7816.h     |   4 +-
 scd/scdaemon.c    |   1 +
 10 files changed, 192 insertions(+), 264 deletions(-)


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




More information about the Gnupg-commits mailing list