[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-144-ge791ac6

by NIIBE Yutaka cvs at cvs.gnupg.org
Tue Feb 5 05:48:41 CET 2013


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  e791ac6683bfb90d5e40c0103324784bd58535c9 (commit)
       via  0407e642f796fb2780a77b7a1a86731d0de27e5d (commit)
       via  bd5eded73a1268afdf81482f8408e5f640abf9c4 (commit)
       via  a9ff97a10f7ae5a703ed1bccba294473ecc88d5d (commit)
       via  334ba6efa5a05d8849fae213128a0505e7615e13 (commit)
       via  d5bf83a24cf3871b7d8cfe61049f70e1e206d09a (commit)
       via  82e1e837c29225cd55642b193cc04ce6191d19bb (commit)
       via  3aae780f9debaeb3560ff866b7e09d0923481c57 (commit)
       via  40a914a2e3052847b49c4b5e8ac8538e97efd18a (commit)
       via  b526f6e223604b7c1852ef2aab9fc1ea691b1181 (commit)
       via  ca89277cb4cb9558da97a71a4cb070cb77c9b536 (commit)
       via  d9f6cc7502793ed41928042cc2f968c8c7effc22 (commit)
      from  65eb98966a569a91c97d0c23ba5582a9a7558de0 (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 e791ac6683bfb90d5e40c0103324784bd58535c9
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Jan 28 11:46:40 2013 +0900

    SCD: Add vendor specific initalization.
    
    * scd/ccid-driver.c (ccid_vendor_specific_init): New.
    (ccid_open_reader): Call ccid_vendor_specific_init.

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index e9f39f4..6d6c3db 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -303,6 +303,9 @@ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
                     size_t *nread, int expected_type, int seqno, int timeout,
                     int no_debug);
 static int abort_cmd (ccid_driver_t handle, int seqno);
+static int send_escape_cmd (ccid_driver_t handle, const unsigned char *data,
+                            size_t datalen, unsigned char *result,
+                            size_t resultmax, size_t *resultlen);
 
 /* Convert a little endian stored 4 byte value into an unsigned
    integer. */
@@ -1525,6 +1528,29 @@ ccid_get_reader_list (void)
 }
 
 
+/* Vendor specific custom initialization.  */
+static int
+ccid_vendor_specific_init (ccid_driver_t handle)
+{
+  if (handle->id_vendor == VENDOR_VEGA && handle->id_product == VEGA_ALPHA)
+    {
+      /*
+       * Vega alpha has a feature to show retry counter on the pinpad
+       * display.  But it assumes that the card returns the value of
+       * retry counter by VERIFY with empty data (return code of
+       * 63Cx).  Unfortunately, existing OpenPGP cards don't support
+       * VERIFY command with empty data.  This vendor specific command
+       * sequence is to disable the feature.
+       */
+      const unsigned char cmd[] = "\xb5\x01\x00\x03\x00";
+
+      return send_escape_cmd (handle, cmd, sizeof (cmd), NULL, 0, NULL);
+    }
+
+  return 0;
+}
+
+
 /* Open the reader with the internal number READERNO and return a
    pointer to be used as handle in HANDLE.  Returns 0 on success. */
 int
@@ -1633,6 +1659,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
         }
     }
 
+  rc = ccid_vendor_specific_init (*handle);
+
  leave:
   free (ifcdesc_extra);
   if (rc)

commit 0407e642f796fb2780a77b7a1a86731d0de27e5d
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Sun Jan 13 12:12:10 2013 +0900

    SCD: Support P=N format for login data.
    
    * scd/app-openpgp.c (parse_login_data): Support P=N format.

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 9c85c61..dc35295 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -602,9 +602,9 @@ count_bits (const unsigned char *a, size_t len)
 
     P=<keypad-request>
 
-    Where KEYPAD_REQUEST is 0 or a pair of two integers: <n>,<m>.
-    0 means use keypad with variable length input.  <n>,<m> means use
-    keypad with fixed length input.  N for user PIN, M for admin PIN.
+    Where KEYPAD_REQUEST is in the format of: <n> or <n>,<m>.
+    N for user PIN, M for admin PIN.  If M is missing it means M=N.
+    0 means to force not to use keypad.
 
 */
 static void
@@ -660,24 +660,22 @@ parse_login_data (app_t app)
 
           if (buflen)
             {
-              if (*buffer == '0')
-                {
-                  buffer++;
-                  buflen--;
-                  if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
-                    goto next;
-                  /* Disable use of pinpad.  */
-                  app->app_local->keypad.specified = 1;
-                }
-              else if (digitp (buffer))
+              if (digitp (buffer))
                 {
                   char *q;
                   int n, m;
 
                   n = strtol (buffer, &q, 10);
-                  if (*q++ != ',' || !digitp (q))
-                    goto next;
-                  m = strtol (q, &q, 10);
+                  if (q >= (char *)buffer + buflen
+                      || *q == '\x18' || *q == '\n')
+                    m = n;
+                  else
+                    {
+                      if (*q++ != ',' || !digitp (q))
+                        goto next;
+                      m = strtol (q, &q, 10);
+                    }
+
                   buffer = q;
                   if (buflen < ((unsigned char *)q - buffer))
                     {
@@ -1540,14 +1538,16 @@ static int
 check_keypad_request (app_t app, pininfo_t *pininfo, int admin_pin)
 {
   if (app->app_local->keypad.specified == 0) /* No preference on card.  */
-    if (pininfo->fixedlen == 0) /* Reader has varlen capability.  */
-      return 0;                 /* Then, use pinpad.  */
-    else
-      /*
-       * Reader has limited capability, and it may not match PIN of
-       * the card.
-       */
-      return 1;
+    {
+      if (pininfo->fixedlen == 0) /* Reader has varlen capability.  */
+        return 0;                 /* Then, use pinpad.  */
+      else
+        /*
+         * Reader has limited capability, and it may not match PIN of
+         * the card.
+         */
+        return 1;
+    }
 
   if (admin_pin)
     pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;

commit bd5eded73a1268afdf81482f8408e5f640abf9c4
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jan 11 13:19:17 2013 +0900

    SCD: Better interoperability.
    
    * scd/apdu.c: Fill bTeoPrologue[2] field.
    --
    ccid-1.4.5 or older requires this field is filled by application.

diff --git a/scd/apdu.c b/scd/apdu.c
index f1f2d01..ef7c54f 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -2084,7 +2084,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   pin_verify[11] = 0x00; /* bMsgIndex */
   pin_verify[12] = 0x00; /* bTeoPrologue[0] */
   pin_verify[13] = 0x00; /* bTeoPrologue[1] */
-  pin_verify[14] = 0x00; /* bTeoPrologue[2] */
+  pin_verify[14] = pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
   pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
   pin_verify[16] = 0x00; /* ulDataLength */
   pin_verify[17] = 0x00; /* ulDataLength */
@@ -2178,7 +2178,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   pin_modify[16] = 0x00; /* bMsgIndex3 */
   pin_modify[17] = 0x00; /* bTeoPrologue[0] */
   pin_modify[18] = 0x00; /* bTeoPrologue[1] */
-  pin_modify[19] = 0x00; /* bTeoPrologue[2] */
+  pin_modify[19] = 2 * pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
   pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
   pin_modify[21] = 0x00; /* ulDataLength */
   pin_modify[22] = 0x00; /* ulDataLength */

commit a9ff97a10f7ae5a703ed1bccba294473ecc88d5d
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Fri Jan 11 10:41:38 2013 +0900

    SCD: Defaults to use pinpad if the reader has the capability.
    
    * scd/app-openpgp.c (struct app_local_s): Remove VARLEN.
    (parse_login_data): "P=0" means to disable pinpad.
    (check_keypad_request): Default is to use pinpad if available.

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 1188770..9c85c61 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -195,7 +195,6 @@ struct app_local_s {
   struct
   {
     unsigned int specified:1;
-    unsigned int varlen:1;
     int fixedlen_user;
     int fixedlen_admin;
   } keypad;
@@ -619,9 +618,8 @@ parse_login_data (app_t app)
   app->app_local->flags.no_sync = 0;
   app->app_local->flags.def_chv2 = 0;
   app->app_local->keypad.specified = 0;
-  app->app_local->keypad.varlen = 0;
-  app->app_local->keypad.fixedlen_user = 6;
-  app->app_local->keypad.fixedlen_admin = 8;
+  app->app_local->keypad.fixedlen_user = -1;
+  app->app_local->keypad.fixedlen_admin = -1;
 
   /* Read the DO.  */
   relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
@@ -668,8 +666,8 @@ parse_login_data (app_t app)
                   buflen--;
                   if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
                     goto next;
+                  /* Disable use of pinpad.  */
                   app->app_local->keypad.specified = 1;
-                  app->app_local->keypad.varlen = 1;
                 }
               else if (digitp (buffer))
                 {
@@ -1534,34 +1532,36 @@ do_readcert (app_t app, const char *certid,
 }
 
 
-/* Decide if we use keypad of reader for PIN input according to the
-   user preference on the card.  Returns 0 if we use keypad, 1 otherwise.  */
+/* Decide if we use the keypad of the reader for PIN input according
+   to the user preference on the card, and the capability of the
+   reader.  This routine is only called when the reader has keypad.
+   Returns 0 if we use keypad, 1 otherwise.  */
 static int
 check_keypad_request (app_t app, pininfo_t *pininfo, int admin_pin)
 {
-  /* User specifies no preference on card, then, use pinentry.  */
-  if (app->app_local->keypad.specified == 0)
-    return 1;
-
-  if (app->app_local->keypad.varlen)
-    if (pininfo->fixedlen == 0)
-      return 0;
+  if (app->app_local->keypad.specified == 0) /* No preference on card.  */
+    if (pininfo->fixedlen == 0) /* Reader has varlen capability.  */
+      return 0;                 /* Then, use pinpad.  */
     else
-      /* On card, user specifies varlen but reader doesn't have the feature.  */
+      /*
+       * Reader has limited capability, and it may not match PIN of
+       * the card.
+       */
       return 1;
+
+  if (admin_pin)
+    pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;
   else
-    {
-      if (admin_pin)
-        pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;
-      else
-        pininfo->fixedlen = app->app_local->keypad.fixedlen_user;
+    pininfo->fixedlen = app->app_local->keypad.fixedlen_user;
 
-      if (pininfo->fixedlen < pininfo->minlen
-          || pininfo->fixedlen > pininfo->maxlen)
-        return 1;
+  if (pininfo->fixedlen < 0    /* User requests disable pinpad.  */
+      || pininfo->fixedlen < pininfo->minlen
+      || pininfo->fixedlen > pininfo->maxlen
+      /* Reader doesn't have the capability to input a PIN which
+       * length is FIXEDLEN.  */)
+    return 1;
 
-      return 0;
-    }
+  return 0;
 }
 
 

commit 334ba6efa5a05d8849fae213128a0505e7615e13
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jan 10 15:58:43 2013 +0900

    SCD: handle keypad request on the card.
    
    * scd/app-openpgp.c: Add 2013.
    (struct app_local_s): Add keypad structure.
    (parse_login_data): Add parsing keypad request on the card.
    (check_keypad_request): New.
    (verify_a_chv, verify_chv3, do_change_pin): Call check_keypad_request
    to determine use of keypad.

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index dcc3120..1188770 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1,6 +1,6 @@
 /* app-openpgp.c - The OpenPGP card application.
  * Copyright (C) 2003, 2004, 2005, 2007, 2008,
- *               2009 Free Software Foundation, Inc.
+ *               2009, 2013 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -191,6 +191,15 @@ struct app_local_s {
     unsigned int def_chv2:1;  /* Use 123456 for CHV2.  */
   } flags;
 
+  /* Keypad request specified on card.  */
+  struct
+  {
+    unsigned int specified:1;
+    unsigned int varlen:1;
+    int fixedlen_user;
+    int fixedlen_admin;
+  } keypad;
+
   struct
   {
     unsigned int n_bits;     /* Size of the modulus in bits.  The rest
@@ -581,17 +590,23 @@ count_bits (const unsigned char *a, size_t len)
    Everything up to a LF is considered a mailbox or account name.  If
    the first LF is followed by DC4 (0x14) control sequence are
    expected up to the next LF.  Control sequences are separated by FS
-   (0x18) and consist of key=value pairs.  There is one key defined:
+   (0x18) and consist of key=value pairs.  There are two keys defined:
 
     F=<flags>
 
-    Were FLAGS is a plain hexadecimal number representing flag values.
+    Where FLAGS is a plain hexadecimal number representing flag values.
     The lsb is here the rightmost bit.  Defined flags bits are:
 
       Bit 0 = CHV1 and CHV2 are not syncronized
       Bit 1 = CHV2 has been been set to the default PIN of "123456"
               (this implies that bit 0 is also set).
 
+    P=<keypad-request>
+
+    Where KEYPAD_REQUEST is 0 or a pair of two integers: <n>,<m>.
+    0 means use keypad with variable length input.  <n>,<m> means use
+    keypad with fixed length input.  N for user PIN, M for admin PIN.
+
 */
 static void
 parse_login_data (app_t app)
@@ -603,6 +618,10 @@ parse_login_data (app_t app)
   /* Set defaults.  */
   app->app_local->flags.no_sync = 0;
   app->app_local->flags.def_chv2 = 0;
+  app->app_local->keypad.specified = 0;
+  app->app_local->keypad.varlen = 0;
+  app->app_local->keypad.fixedlen_user = 6;
+  app->app_local->keypad.fixedlen_admin = 8;
 
   /* Read the DO.  */
   relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
@@ -628,11 +647,56 @@ parse_login_data (app_t app)
              any leading digits but bail out on invalid characters. */
           for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
             lastdig = xtoi_1 (p);
+          buffer = p;
+          buflen = len;
           if (len && !(*p == '\n' || *p == '\x18'))
             goto next;  /* Invalid characters in field.  */
           app->app_local->flags.no_sync = !!(lastdig & 1);
           app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
         }
+      else if (buflen > 1 && *buffer == 'P' && buffer[1] == '=')
+        {
+          /* Keypad request control sequence found.  */
+          buffer += 2;
+          buflen -= 2;
+
+          if (buflen)
+            {
+              if (*buffer == '0')
+                {
+                  buffer++;
+                  buflen--;
+                  if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
+                    goto next;
+                  app->app_local->keypad.specified = 1;
+                  app->app_local->keypad.varlen = 1;
+                }
+              else if (digitp (buffer))
+                {
+                  char *q;
+                  int n, m;
+
+                  n = strtol (buffer, &q, 10);
+                  if (*q++ != ',' || !digitp (q))
+                    goto next;
+                  m = strtol (q, &q, 10);
+                  buffer = q;
+                  if (buflen < ((unsigned char *)q - buffer))
+                    {
+                      buflen = 0;
+                      break;
+                    }
+                  else
+                    buflen -= ((unsigned char *)q - buffer);
+
+                  if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
+                    goto next;
+                  app->app_local->keypad.specified = 1;
+                  app->app_local->keypad.fixedlen_user = n;
+                  app->app_local->keypad.fixedlen_admin = m;
+                }
+            }
+        }
     next:
       for (; buflen && *buffer != '\x18'; buflen--, buffer++)
         if (*buffer == '\n')
@@ -1470,6 +1534,37 @@ do_readcert (app_t app, const char *certid,
 }
 
 
+/* Decide if we use keypad of reader for PIN input according to the
+   user preference on the card.  Returns 0 if we use keypad, 1 otherwise.  */
+static int
+check_keypad_request (app_t app, pininfo_t *pininfo, int admin_pin)
+{
+  /* User specifies no preference on card, then, use pinentry.  */
+  if (app->app_local->keypad.specified == 0)
+    return 1;
+
+  if (app->app_local->keypad.varlen)
+    if (pininfo->fixedlen == 0)
+      return 0;
+    else
+      /* On card, user specifies varlen but reader doesn't have the feature.  */
+      return 1;
+  else
+    {
+      if (admin_pin)
+        pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;
+      else
+        pininfo->fixedlen = app->app_local->keypad.fixedlen_user;
+
+      if (pininfo->fixedlen < pininfo->minlen
+          || pininfo->fixedlen > pininfo->maxlen)
+        return 1;
+
+      return 0;
+    }
+}
+
+
 /* Verify a CHV either using using the pinentry or if possibile by
    using a keypad.  PINCB and PINCB_ARG describe the usual callback
    for the pinentry.  CHVNO must be either 1 or 2. SIGCOUNT is only
@@ -1537,7 +1632,8 @@ verify_a_chv (app_t app,
 
 
   if (!opt.disable_keypad
-      && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
+      && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
+      && !check_keypad_request (app, &pininfo, 0))
     {
       /* The reader supports the verify command through the keypad.
          Note that the pincb appends a text to the prompt telling the
@@ -1720,7 +1816,8 @@ verify_chv3 (app_t app,
         return rc;
 
       if (!opt.disable_keypad
-          && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
+          && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
+          && !check_keypad_request (app, &pininfo, 1))
         {
           /* The reader supports the verify command through the keypad. */
           rc = pincb (pincb_arg, prompt, NULL);
@@ -1970,7 +2067,8 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
 
       if (!opt.disable_keypad
           && !iso7816_check_keypad (app->slot,
-                                    ISO7816_CHANGE_REFERENCE_DATA, &pininfo))
+                                    ISO7816_CHANGE_REFERENCE_DATA, &pininfo)
+          && !check_keypad_request (app, &pininfo, chvno == 3))
         use_keypad = 1;
 
       if (reset_mode)

commit d5bf83a24cf3871b7d8cfe61049f70e1e206d09a
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jan 10 15:52:24 2013 +0900

    SCD: Minor fix of ccid-driver.
    
    * scd/ccid-driver.c (VENDOR_VEGA): Fix typo.

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 95e85d9..e9f39f4 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -209,7 +209,7 @@ enum {
   VENDOR_SCM    = 0x04e6,
   VENDOR_OMNIKEY= 0x076b,
   VENDOR_GEMPC  = 0x08e6,
-  VENDER_VEGA   = 0x0982,
+  VENDOR_VEGA   = 0x0982,
   VENDOR_KAAN   = 0x0d46,
   VENDOR_FSIJ   = 0x234b,
   VENDOR_VASCO  = 0x1a44

commit 82e1e837c29225cd55642b193cc04ce6191d19bb
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Thu Jan 10 10:49:27 2013 +0900

    SCD: Add support of Covadis VEGA_ALPHA reader.
    
    * scd/ccid-driver.c: Add 2013.
    (VENDER_VEGA, VEGA_ALPHA):New.
    (ccid_transceive_secure): VEGA_ALPHA is same firmware as GEMPC_PINPAD.
    Change bNumberMessage to 0x01, as it works better (was: 0xff).

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 83b419a..95e85d9 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -1,6 +1,6 @@
 /* ccid-driver.c - USB ChipCardInterfaceDevices driver
  * Copyright (C) 2003, 2004, 2005, 2006, 2007
- *               2008, 2009  Free Software Foundation, Inc.
+ *               2008, 2009, 2013  Free Software Foundation, Inc.
  * Written by Werner Koch.
  *
  * This file is part of GnuPG.
@@ -209,6 +209,7 @@ enum {
   VENDOR_SCM    = 0x04e6,
   VENDOR_OMNIKEY= 0x076b,
   VENDOR_GEMPC  = 0x08e6,
+  VENDER_VEGA   = 0x0982,
   VENDOR_KAAN   = 0x0d46,
   VENDOR_FSIJ   = 0x234b,
   VENDOR_VASCO  = 0x1a44
@@ -222,7 +223,8 @@ enum {
 #define SCM_SPR532      0xe003
 #define CHERRY_ST2000   0x003e
 #define VASCO_920       0x0920
-#define GEMPC_PINPAD	0x3478
+#define GEMPC_PINPAD    0x3478
+#define VEGA_ALPHA      0x0008
 
 /* A list and a table with special transport descriptions. */
 enum {
@@ -2382,7 +2384,7 @@ update_param_by_atr (unsigned char *param, unsigned char *atr, size_t atrlen)
   NEXTBYTE ();
 
   if (atr[i] == 0x3F)
-    param[1] |= 0x02;		/* Convention is inverse.  */
+    param[1] |= 0x02;           /* Convention is inverse.  */
   NEXTBYTE ();
 
   y = (atr[i] >> 4);
@@ -2391,91 +2393,91 @@ update_param_by_atr (unsigned char *param, unsigned char *atr, size_t atrlen)
 
   if ((y & 1))
     {
-      param[0] = atr[i];	/* TA1 - Fi & Di */
+      param[0] = atr[i];        /* TA1 - Fi & Di */
       NEXTBYTE ();
     }
 
   if ((y & 2))
-    NEXTBYTE ();		/* TB1 - ignore */
+    NEXTBYTE ();                /* TB1 - ignore */
 
   if ((y & 4))
     {
-      param[2] = atr[i];	/* TC1 - Guard Time */
+      param[2] = atr[i];        /* TC1 - Guard Time */
       NEXTBYTE ();
     }
 
   if ((y & 8))
     {
-      y = (atr[i] >> 4);	/* TD1 */
+      y = (atr[i] >> 4);        /* TD1 */
       t = atr[i] & 0x0f;
       NEXTBYTE ();
 
       if ((y & 1))
-	{			/* TA2 - PPS mode */
-	  if ((atr[i] & 0x0f) != 1)
-	    return -2;		/* Wrong card protocol (!= 1).  */
+        {                       /* TA2 - PPS mode */
+          if ((atr[i] & 0x0f) != 1)
+            return -2;          /* Wrong card protocol (!= 1).  */
 
-	  if ((atr[i] & 0x10) != 0x10)
-	    return -3; /* Transmission parameters are implicitly defined. */
+          if ((atr[i] & 0x10) != 0x10)
+            return -3; /* Transmission parameters are implicitly defined. */
 
-	  negotiable = 0;	/* TA2 means specific mode.  */
-	  NEXTBYTE ();
-	}
+          negotiable = 0;       /* TA2 means specific mode.  */
+          NEXTBYTE ();
+        }
 
       if ((y & 2))
-	NEXTBYTE ();		/* TB2 - ignore */
+        NEXTBYTE ();            /* TB2 - ignore */
 
       if ((y & 4))
-	NEXTBYTE ();		/* TC2 - ignore */
+        NEXTBYTE ();            /* TC2 - ignore */
 
       if ((y & 8))
-	{
-	  y = (atr[i] >> 4);	/* TD2 */
-	  t = atr[i] & 0x0f;
-	  NEXTBYTE ();
-	}
+        {
+          y = (atr[i] >> 4);    /* TD2 */
+          t = atr[i] & 0x0f;
+          NEXTBYTE ();
+        }
       else
-	y = 0;
+        y = 0;
 
       while (y)
-	{
-	  if ((y & 1))
-	    {			/* TAx */
-	      if (t == 1)
-		param[5] = atr[i]; /* IFSC */
-	      else if (t == 15)
-		/* XXX: check voltage? */
-		param[4] = (atr[i] >> 6); /* ClockStop */
-
-	      NEXTBYTE ();
-	    }
-
-	  if ((y & 2))
-	    {
-	      if (t == 1)
-		param[3] = atr[i]; /* TBx - BWI & CWI */
-	      NEXTBYTE ();
-	    }
-
-	  if ((y & 4))
-	    {
-	      if (t == 1)
-		param[1] |= (atr[i] & 0x01); /* TCx - LRC/CRC */
-	      NEXTBYTE ();
-
-	      if (param[1] & 0x01)
-		return -4;	/* CRC not supported yet.  */
-	    }
-
-	  if ((y & 8))
-	    {
-	      y = (atr[i] >> 4); /* TDx */
-	      t = atr[i] & 0x0f;
-	      NEXTBYTE ();
-	    }
-	  else
-	    y = 0;
-	}
+        {
+          if ((y & 1))
+            {                   /* TAx */
+              if (t == 1)
+                param[5] = atr[i]; /* IFSC */
+              else if (t == 15)
+                /* XXX: check voltage? */
+                param[4] = (atr[i] >> 6); /* ClockStop */
+
+              NEXTBYTE ();
+            }
+
+          if ((y & 2))
+            {
+              if (t == 1)
+                param[3] = atr[i]; /* TBx - BWI & CWI */
+              NEXTBYTE ();
+            }
+
+          if ((y & 4))
+            {
+              if (t == 1)
+                param[1] |= (atr[i] & 0x01); /* TCx - LRC/CRC */
+              NEXTBYTE ();
+
+              if (param[1] & 0x01)
+                return -4;      /* CRC not supported yet.  */
+            }
+
+          if ((y & 8))
+            {
+              y = (atr[i] >> 4); /* TDx */
+              t = atr[i] & 0x0f;
+              NEXTBYTE ();
+            }
+          else
+            y = 0;
+        }
     }
 
   i += historical_bytes_num - 1;
@@ -2604,16 +2606,16 @@ ccid_get_atr (ccid_driver_t handle,
       msglen = 10;
       rc = bulk_out (handle, msg, msglen, 0);
       if (!rc)
-	rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
-		      seqno, 2000, 0);
+        rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
+                      seqno, 2000, 0);
       if (rc)
-	DEBUGOUT ("GetParameters failed\n");
+        DEBUGOUT ("GetParameters failed\n");
       else if (msglen == 17 && msg[9] == 1)
-	got_param = 1;
+        got_param = 1;
     }
   else if (handle->auto_pps)
     ;
-  else if (rc == 1)		/* It's negotiable, send PPS.  */
+  else if (rc == 1)             /* It's negotiable, send PPS.  */
     {
       msg[0] = PC_to_RDR_XfrBlock;
       msg[5] = 0; /* slot */
@@ -2621,33 +2623,33 @@ ccid_get_atr (ccid_driver_t handle,
       msg[7] = 0;
       msg[8] = 0;
       msg[9] = 0;
-      msg[10] = 0xff;		/* PPSS */
-      msg[11] = 0x11;		/* PPS0: PPS1, Protocol T=1 */
-      msg[12] = param[0];	/* PPS1: Fi / Di */
+      msg[10] = 0xff;           /* PPSS */
+      msg[11] = 0x11;           /* PPS0: PPS1, Protocol T=1 */
+      msg[12] = param[0];       /* PPS1: Fi / Di */
       msg[13] = 0xff ^ 0x11 ^ param[0]; /* PCK */
       set_msg_len (msg, 4);
       msglen = 10 + 4;
 
       rc = bulk_out (handle, msg, msglen, 0);
       if (rc)
-	return rc;
+        return rc;
 
       rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
-		    seqno, 5000, 0);
+                    seqno, 5000, 0);
       if (rc)
-	return rc;
+        return rc;
 
       if (msglen != 10 + 4)
-	{
-	  DEBUGOUT_1 ("Setting PPS failed: %d\n", msglen);
-	  return CCID_DRIVER_ERR_CARD_IO_ERROR;
-	}
+        {
+          DEBUGOUT_1 ("Setting PPS failed: %d\n", msglen);
+          return CCID_DRIVER_ERR_CARD_IO_ERROR;
+        }
 
       if (msg[10] != 0xff || msg[11] != 0x11 || msg[12] != param[0])
-	{
-	  DEBUGOUT_1 ("Setting PPS failed: 0x%02x\n", param[0]);
-	  return CCID_DRIVER_ERR_CARD_IO_ERROR;
-	}
+        {
+          DEBUGOUT_1 ("Setting PPS failed: 0x%02x\n", param[0]);
+          return CCID_DRIVER_ERR_CARD_IO_ERROR;
+        }
     }
 
   /* Setup parameters to select T=1. */
@@ -3298,7 +3300,7 @@ ccid_transceive (ccid_driver_t handle,
 int
 ccid_transceive_secure (ccid_driver_t handle,
                         const unsigned char *apdu_buf, size_t apdu_buflen,
-			pininfo_t *pininfo,
+                        pininfo_t *pininfo,
                         unsigned char *resp, size_t maxresplen, size_t *nresp)
 {
   int rc;
@@ -3360,16 +3362,17 @@ ccid_transceive_secure (ccid_driver_t handle,
       if (handle->id_product != CHERRY_ST2000)
         cherry_mode = 1;
       break;
-    case VENDOR_GEMPC:
-      if (handle->id_product == GEMPC_PINPAD)
-	{
-	  enable_varlen = 0;
-	  pininfo->minlen = 4;
-	  pininfo->maxlen = 8;
-	  break;
-	}
-      /* fall through */
     default:
+      if ((handle->id_vendor == VENDOR_GEMPC &&
+           handle->id_product == GEMPC_PINPAD)
+          || (handle->id_vendor == VENDOR_VEGA &&
+              handle->id_product == VEGA_ALPHA))
+        {
+          enable_varlen = 0;
+          pininfo->minlen = 4;
+          pininfo->maxlen = 8;
+          break;
+        }
      return CCID_DRIVER_ERR_NOT_SUPPORTED;
     }
 
@@ -3412,8 +3415,8 @@ ccid_transceive_secure (ccid_driver_t handle,
   else
     {
       msg[13] = pininfo->fixedlen; /* bmPINBlockString:
-				      0 bits of pin length to insert.
-				      PIN block size by fixedlen.  */
+                                      0 bits of pin length to insert.
+                                      PIN block size by fixedlen.  */
       msg[14] = 0x00; /* bmPINLengthFormat:
                          Units are bytes, position is 0. */
     }
@@ -3445,7 +3448,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   msglen++;
 
   if (apdu_buf[1] == 0x20)
-    msg[msglen++] = 0xff; /* bNumberMessage: Default. */
+    msg[msglen++] = 0x01; /* bNumberMessage. */
   else
     msg[msglen++] = 0x03; /* bNumberMessage. */
 

commit 3aae780f9debaeb3560ff866b7e09d0923481c57
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Jan 9 16:40:41 2013 +0900

    SCD: Support fixed length PIN input for keypad (PC/SC).
    
    * scd/apdu.c (pcsc_keypad_verify): SUpport fixed length PIN input for
    keypad.
    (pcsc_keypad_modify): Likewise.
    * scd/ccid-driver.c (ccid_transceive_secure): Clean up.

diff --git a/scd/apdu.c b/scd/apdu.c
index a207f9d..f1f2d01 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -2042,7 +2042,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
 {
   int sw;
   unsigned char *pin_verify;
-  int len = PIN_VERIFY_STRUCTURE_SIZE;
+  int len = PIN_VERIFY_STRUCTURE_SIZE + pininfo->fixedlen;
   unsigned char result[2];
   size_t resultlen = 2;
 
@@ -2050,7 +2050,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
       && (sw = reset_pcsc_reader (slot)))
     return sw;
 
-  if (pininfo->fixedlen != 0)
+  if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
     return SW_NOT_SUPPORTED;
 
   if (!pininfo->minlen)
@@ -2071,7 +2071,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   pin_verify[0] = 0x00; /* bTimerOut */
   pin_verify[1] = 0x00; /* bTimerOut2 */
   pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
-  pin_verify[3] = 0x00; /* bmPINBlockString */
+  pin_verify[3] = pininfo->fixedlen; /* bmPINBlockString */
   pin_verify[4] = 0x00; /* bmPINLengthFormat */
   pin_verify[5] = pininfo->maxlen; /* wPINMaxExtraDigit */
   pin_verify[6] = pininfo->minlen; /* wPINMaxExtraDigit */
@@ -2085,7 +2085,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   pin_verify[12] = 0x00; /* bTeoPrologue[0] */
   pin_verify[13] = 0x00; /* bTeoPrologue[1] */
   pin_verify[14] = 0x00; /* bTeoPrologue[2] */
-  pin_verify[15] = 0x05; /* ulDataLength */
+  pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
   pin_verify[16] = 0x00; /* ulDataLength */
   pin_verify[17] = 0x00; /* ulDataLength */
   pin_verify[18] = 0x00; /* ulDataLength */
@@ -2093,7 +2093,9 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   pin_verify[20] = ins; /* abData[1] */
   pin_verify[21] = p0; /* abData[2] */
   pin_verify[22] = p1; /* abData[3] */
-  pin_verify[23] = 0x00; /* abData[4] */
+  pin_verify[23] = pininfo->fixedlen; /* abData[4] */
+  if (pininfo->fixedlen)
+    memset (&pin_verify[24], 0xff, pininfo->fixedlen);
 
   if (DBG_CARD_IO)
     log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
@@ -2123,7 +2125,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
 {
   int sw;
   unsigned char *pin_modify;
-  int len = PIN_MODIFY_STRUCTURE_SIZE;
+  int len = PIN_MODIFY_STRUCTURE_SIZE + 2 * pininfo->fixedlen;
   unsigned char result[2];
   size_t resultlen = 2;
 
@@ -2131,7 +2133,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
       && (sw = reset_pcsc_reader (slot)))
     return sw;
 
-  if (pininfo->fixedlen != 0)
+  if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
     return SW_NOT_SUPPORTED;
 
   if (!pininfo->minlen)
@@ -2152,10 +2154,10 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   pin_modify[0] = 0x00; /* bTimerOut */
   pin_modify[1] = 0x00; /* bTimerOut2 */
   pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
-  pin_modify[3] = 0x00; /* bmPINBlockString */
+  pin_modify[3] = pininfo->fixedlen; /* bmPINBlockString */
   pin_modify[4] = 0x00; /* bmPINLengthFormat */
   pin_modify[5] = 0x00; /* bInsertionOffsetOld */
-  pin_modify[6] = 0x00; /* bInsertionOffsetNew */
+  pin_modify[6] = pininfo->fixedlen; /* bInsertionOffsetNew */
   pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
   pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
   pin_modify[9] = (p0 == 0 ? 0x03 : 0x01);
@@ -2177,7 +2179,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   pin_modify[17] = 0x00; /* bTeoPrologue[0] */
   pin_modify[18] = 0x00; /* bTeoPrologue[1] */
   pin_modify[19] = 0x00; /* bTeoPrologue[2] */
-  pin_modify[20] = 0x05; /* ulDataLength */
+  pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
   pin_modify[21] = 0x00; /* ulDataLength */
   pin_modify[22] = 0x00; /* ulDataLength */
   pin_modify[23] = 0x00; /* ulDataLength */
@@ -2185,7 +2187,9 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   pin_modify[25] = ins; /* abData[1] */
   pin_modify[26] = p0; /* abData[2] */
   pin_modify[27] = p1; /* abData[3] */
-  pin_modify[28] = 0x00; /* abData[4] */
+  pin_modify[28] = 2 * pininfo->fixedlen; /* abData[4] */
+  if (pininfo->fixedlen)
+    memset (&pin_modify[29], 0xff, 2 * pininfo->fixedlen);
 
   if (DBG_CARD_IO)
     log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 3244c71..83b419a 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -3411,14 +3411,9 @@ ccid_transceive_secure (ccid_driver_t handle,
     }
   else
     {
-      if (pininfo->fixedlen == 0)
-	msg[13] = 0x00; /* bmPINBlockString:
-			   0 bits of pin length to insert.
-			   0 bytes of PIN block size.  */
-      else
-	msg[13] = pininfo->fixedlen; /* bmPINBlockString:
-					0 bits of pin length to insert.
-					PIN block size by fixedlen.  */
+      msg[13] = pininfo->fixedlen; /* bmPINBlockString:
+				      0 bits of pin length to insert.
+				      PIN block size by fixedlen.  */
       msg[14] = 0x00; /* bmPINLengthFormat:
                          Units are bytes, position is 0. */
     }
@@ -3427,10 +3422,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   if (apdu_buf[1] == 0x24)
     {
       msg[msglen++] = 0;    /* bInsertionOffsetOld */
-      if (pininfo->fixedlen == 0)
-	msg[msglen++] = 0;    /* bInsertionOffsetNew */
-      else
-	msg[msglen++] = pininfo->fixedlen;    /* bInsertionOffsetNew */
+      msg[msglen++] = pininfo->fixedlen;    /* bInsertionOffsetNew */
     }
 
   /* The following is a little endian word. */

commit 40a914a2e3052847b49c4b5e8ac8538e97efd18a
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Jan 9 16:23:55 2013 +0900

    SCD: Support fixed length PIN input for keypad.
    
    * scd/iso7816.h (struct pininfo_s): Remove MODE and add FIXEDLEN.
    * scd/app-dinsig.c (verify_pin): Initialize FIXEDLEN to unknown.
    * scd/app-nks.c (verify_pin): Likewise.
    * scd/app-openpgp.c (verify_a_chv, verify_chv3, do_change_pin):
    Likewise.
    * scd/apdu.c (check_pcsc_keypad): Add comment.
    (pcsc_keypad_verify, pcsc_keypad_modify): PC/SC driver only support
    readers with the feature of variable length input (yet).
    (apdu_check_keypad): Set FIXEDLEN.
    * scd/ccid-driver.c (ccid_transceive_secure): Add GEMPC_PINPAD
    specific settings.
    Support fixed length PIN input for keypad.

diff --git a/scd/apdu.c b/scd/apdu.c
index 5a58cfd..a207f9d 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -1986,7 +1986,7 @@ check_pcsc_keypad (int slot, int command, pininfo_t *pininfo)
   size_t len = 256;
   int sw;
 
-  (void)pininfo;
+  (void)pininfo;      /* XXX: Identify reader and set pininfo->fixedlen.  */
 
  check_again:
   if (command == ISO7816_VERIFY)
@@ -2050,7 +2050,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
       && (sw = reset_pcsc_reader (slot)))
     return sw;
 
-  if (pininfo->mode != 1)
+  if (pininfo->fixedlen != 0)
     return SW_NOT_SUPPORTED;
 
   if (!pininfo->minlen)
@@ -2131,7 +2131,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
       && (sw = reset_pcsc_reader (slot)))
     return sw;
 
-  if (pininfo->mode != 1)
+  if (pininfo->fixedlen != 0)
     return SW_NOT_SUPPORTED;
 
   if (!pininfo->minlen)
@@ -3397,7 +3397,7 @@ apdu_check_keypad (int slot, int command, pininfo_t *pininfo)
     return SW_HOST_NO_DRIVER;
 
   if (opt.enable_keypad_varlen)
-    pininfo->mode = 0;
+    pininfo->fixedlen = 0;
 
   if (reader_table[slot].check_keypad)
     {
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index f3f7d4b..9d4ebe2 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -288,7 +288,7 @@ verify_pin (app_t app,
     return 0;  /* No need to verify it again.  */
 
   memset (&pininfo, 0, sizeof pininfo);
-  pininfo.mode = 1;
+  pininfo.fixedlen = -1;
   pininfo.minlen = 6;
   pininfo.maxlen = 8;
 
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 4e7a43c..8a48871 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -788,7 +788,7 @@ verify_pin (app_t app, int pwid, const char *desc,
     desc = "PIN";
 
   memset (&pininfo, 0, sizeof pininfo);
-  pininfo.mode = 1;
+  pininfo.fixedlen = -1;
   pininfo.minlen = 6;
   pininfo.maxlen = 16;
 
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 968ef98..dcc3120 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1516,7 +1516,7 @@ verify_a_chv (app_t app,
     }
 
   memset (&pininfo, 0, sizeof pininfo);
-  pininfo.mode = 1;
+  pininfo.fixedlen = -1;
   pininfo.minlen = minlen;
 
 
@@ -1712,7 +1712,7 @@ verify_chv3 (app_t app,
       char *prompt;
 
       memset (&pininfo, 0, sizeof pininfo);
-      pininfo.mode = 1;
+      pininfo.fixedlen = -1;
       pininfo.minlen = minlen;
 
       rc = build_enter_admin_pin_prompt (app, &prompt);
@@ -1923,7 +1923,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
 
   (void)ctrl;
   memset (&pininfo, 0, sizeof pininfo);
-  pininfo.mode = 1;
+  pininfo.fixedlen = -1;
   pininfo.minlen = minlen;
 
   if (reset_mode && chvno == 3)
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index c16c7ac..3244c71 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -3361,23 +3361,27 @@ ccid_transceive_secure (ccid_driver_t handle,
         cherry_mode = 1;
       break;
     case VENDOR_GEMPC:
-      enable_varlen = 0;
       if (handle->id_product == GEMPC_PINPAD)
-	break;
+	{
+	  enable_varlen = 0;
+	  pininfo->minlen = 4;
+	  pininfo->maxlen = 8;
+	  break;
+	}
       /* fall through */
     default:
      return CCID_DRIVER_ERR_NOT_SUPPORTED;
     }
 
   if (enable_varlen)
-    pininfo->mode = 0;
-
-  if (pininfo->mode != 0 && pininfo->mode != 1)
-    return CCID_DRIVER_ERR_NOT_SUPPORTED;
+    pininfo->fixedlen = 0;
 
   if (testmode)
     return 0; /* Success */
 
+  if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
+    return CCID_DRIVER_ERR_NOT_SUPPORTED;
+
   msg = send_buffer;
   if (handle->id_vendor == VENDOR_SCM)
     {
@@ -3407,9 +3411,14 @@ ccid_transceive_secure (ccid_driver_t handle,
     }
   else
     {
-      msg[13] = 0x00; /* bmPINBlockString:
-                         0 bits of pin length to insert.
-                         0 bytes of PIN block size.  */
+      if (pininfo->fixedlen == 0)
+	msg[13] = 0x00; /* bmPINBlockString:
+			   0 bits of pin length to insert.
+			   0 bytes of PIN block size.  */
+      else
+	msg[13] = pininfo->fixedlen; /* bmPINBlockString:
+					0 bits of pin length to insert.
+					PIN block size by fixedlen.  */
       msg[14] = 0x00; /* bmPINLengthFormat:
                          Units are bytes, position is 0. */
     }
@@ -3418,7 +3427,10 @@ ccid_transceive_secure (ccid_driver_t handle,
   if (apdu_buf[1] == 0x24)
     {
       msg[msglen++] = 0;    /* bInsertionOffsetOld */
-      msg[msglen++] = 0;    /* bInsertionOffsetNew */
+      if (pininfo->fixedlen == 0)
+	msg[msglen++] = 0;    /* bInsertionOffsetNew */
+      else
+	msg[msglen++] = pininfo->fixedlen;    /* bInsertionOffsetNew */
     }
 
   /* The following is a little endian word. */
@@ -3457,10 +3469,18 @@ ccid_transceive_secure (ccid_driver_t handle,
       msg[msglen++] = 2;    /* bMsgIndex3. */
     }
 
+  /* Calculate Lc.  */
+  n = pininfo->fixedlen;
+  if (apdu_buf[1] == 0x24)
+    n += pininfo->fixedlen;
+
   /* bTeoProlog follows: */
   msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0;
   msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */
-  msg[msglen++] = 0; /* The apdulen will be filled in by the reader.  */
+  if (n)
+    msg[msglen++] = n + 5; /* apdulen should be filled for fixed length.  */
+  else
+    msg[msglen++] = 0; /* The apdulen will be filled in by the reader.  */
   /* APDU follows:  */
   msg[msglen++] = apdu_buf[0]; /* CLA */
   msg[msglen++] = apdu_buf[1]; /* INS */
@@ -3468,6 +3488,12 @@ ccid_transceive_secure (ccid_driver_t handle,
   msg[msglen++] = apdu_buf[3]; /* P2 */
   if (cherry_mode)
     msg[msglen++] = 0;
+  else if (pininfo->fixedlen != 0)
+    {
+      msg[msglen++] = n;
+      memset (&msg[msglen], 0xff, n);
+      msglen += n;
+    }
   /* An EDC is not required. */
   set_msg_len (msg, msglen - 10);
 
diff --git a/scd/iso7816.h b/scd/iso7816.h
index e6dfecd..bf195ea 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -34,7 +34,12 @@
    ccid-driver.c for details. */
 struct pininfo_s
 {
-  int mode;    /* 0: Use variable length input.  1: Use fixed length input. */
+  int fixedlen;  /*
+		  * -1: Variable length input is not supported,
+		  *     no information of fixed length yet.
+		  *  0: Use variable length input.
+		  * >0: Fixed length of PIN.
+		  */
   int minlen;
   int maxlen;
 };

commit b526f6e223604b7c1852ef2aab9fc1ea691b1181
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Jan 9 14:10:08 2013 +0900

    SCD: API cleanup for keypad handling.
    
    * scd/iso7816.h (struct pininfo_s): Rename from iso7816_pininfo_s.
    Change meaning of MODE.
    (pininfo_t): Rename from iso7816_pininfo_t.
    * scd/sc-copykeys.c: Include "iso7816.h".
    * scd/scdaemon.c, scd/command.c: Likewise.
    * scd/ccid-driver.c: Include "scdaemon.h" and "iso7816.h".
    (ccid_transceive_secure): Follow the change of PININFO_T.
    * scd/app.c: Include "apdu.h" after "iso7816.h".
    * scd/iso7816.c (iso7816_check_keypad, iso7816_verify_kp)
    (iso7816_change_reference_data_kp): Follow the change of API.
    * scd/apdu.c (struct reader_table_s): Change API of CHECK_KEYPAD,
    KEYPAD_VERIFY, KEYPAD_MODIFY to have arg of PININFO_T.
    (check_pcsc_keypad, check_ccid_keypad): Likewise.
    (apdu_check_keypad, apdu_keypad_verify, apdu_keypad_modify): Likewise.
    (pcsc_keypad_verify, pcsc_keypad_modify, ct_send_apdu)
    (pcsc_send_apdu_direct,  pcsc_send_apdu_wrapped, pcsc_send_apdu)
    (send_apdu_ccid, ccid_keypad_operation, my_rapdu_send_apdu, send_apdu)
    (send_le): Follow the change of API.
    * scd/apdu.h (apdu_check_keypad, apdu_keypad_verify)
    (apdu_keypad_modify): Change the API.
    * scd/app-dinsig.c, scd/app-nks.c, scd/app-openpgp.c: Follow the
    change.

diff --git a/scd/apdu.c b/scd/apdu.c
index f66db4d..5a58cfd 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -60,10 +60,9 @@
 #include "exechelp.h"
 #endif /* GNUPG_MAJOR_VERSION != 1 */
 
+#include "iso7816.h"
 #include "apdu.h"
 #include "ccid-driver.h"
-#include "iso7816.h"
-
 
 /* Due to conflicting use of threading libraries we usually can't link
    against libpcsclite.   Instead we use a wrapper program.  */
@@ -83,8 +82,6 @@
 #define DLSTDCALL
 #endif
 
-#define pininfo_s iso7816_pininfo_s
-
 /* A structure to collect information pertaining to one reader
    slot. */
 struct reader_table_s {
@@ -99,12 +96,12 @@ struct reader_table_s {
   int (*reset_reader)(int);
   int (*get_status_reader)(int, unsigned int *);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
-                          unsigned char *, size_t *, struct pininfo_s *);
-  int (*check_keypad)(int, int, int, int, int);
+                          unsigned char *, size_t *, pininfo_t *);
+  int (*check_keypad)(int, int, pininfo_t *);
   void (*dump_status_reader)(int);
   int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
-  int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *);
-  int (*keypad_modify)(int, int, int, int, int, struct pininfo_s *);
+  int (*keypad_verify)(int, int, int, int, int, pininfo_t *);
+  int (*keypad_modify)(int, int, int, int, int, pininfo_t *);
 
   struct {
     ccid_driver_t handle;
@@ -322,12 +319,11 @@ static int reset_pcsc_reader (int slot);
 static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
                                      unsigned int *status,
                                      unsigned int *changed);
-static int check_pcsc_keypad (int slot, int command, int pin_mode,
-                              int pinlen_min, int pinlen_max);
+static int check_pcsc_keypad (int slot, int command, pininfo_t *pininfo);
 static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
-                               struct pininfo_s *pininfo);
+                               pininfo_t *pininfo);
 static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
-                               struct pininfo_s *pininfo);
+                               pininfo_t *pininfo);
 
 
 
@@ -600,7 +596,7 @@ ct_get_status (int slot, unsigned int *status)
    set to BUFLEN.  Returns: CT API error code. */
 static int
 ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-              unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
+              unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
 {
   int rc;
   unsigned char dad[1], sad[1];
@@ -1031,7 +1027,7 @@ pcsc_get_status (int slot, unsigned int *status)
 static int
 pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
                        unsigned char *buffer, size_t *buflen,
-                       struct pininfo_s *pininfo)
+                       pininfo_t *pininfo)
 {
   long err;
   struct pcsc_io_request_s send_pci;
@@ -1067,7 +1063,7 @@ pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
 static int
 pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
                         unsigned char *buffer, size_t *buflen,
-                        struct pininfo_s *pininfo)
+                        pininfo_t *pininfo)
 {
   long err;
   reader_table_t slotp;
@@ -1187,7 +1183,7 @@ pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
 static int
 pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
                 unsigned char *buffer, size_t *buflen,
-                struct pininfo_s *pininfo)
+                pininfo_t *pininfo)
 {
 #ifdef NEED_PCSC_WRAPPER
   return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo);
@@ -1984,16 +1980,13 @@ open_pcsc_reader (const char *portstr)
 /* Check whether the reader supports the ISO command code COMMAND
    on the keypad.  Return 0 on success.  */
 static int
-check_pcsc_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max)
+check_pcsc_keypad (int slot, int command, pininfo_t *pininfo)
 {
   unsigned char buf[256];
   size_t len = 256;
   int sw;
 
-  (void)pin_mode;
-  (void)pinlen_min;
-  (void)pinlen_max;
+  (void)pininfo;
 
  check_again:
   if (command == ISO7816_VERIFY)
@@ -2045,7 +2038,7 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
 #define PIN_VERIFY_STRUCTURE_SIZE 24
 static int
 pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
-                    struct pininfo_s *pininfo)
+                    pininfo_t *pininfo)
 {
   int sw;
   unsigned char *pin_verify;
@@ -2126,7 +2119,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
 #define PIN_MODIFY_STRUCTURE_SIZE 29
 static int
 pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
-                    struct pininfo_s *pininfo)
+                    pininfo_t *pininfo)
 {
   int sw;
   unsigned char *pin_modify;
@@ -2297,7 +2290,7 @@ get_status_ccid (int slot, unsigned int *status)
 static int
 send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
                 unsigned char *buffer, size_t *buflen,
-                struct pininfo_s *pininfo)
+                pininfo_t *pininfo)
 {
   long err;
   size_t maxbuflen;
@@ -2313,10 +2306,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
   maxbuflen = *buflen;
   if (pininfo)
     err = ccid_transceive_secure (reader_table[slot].ccid.handle,
-                                  apdu, apdulen,
-                                  pininfo->mode,
-                                  pininfo->minlen,
-                                  pininfo->maxlen,
+                                  apdu, apdulen, pininfo,
                                   buffer, maxbuflen, buflen);
   else
     err = ccid_transceive (reader_table[slot].ccid.handle,
@@ -2334,22 +2324,19 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
    on the keypad.  Return 0 on success.  For a description of the pin
    parameters, see ccid-driver.c */
 static int
-check_ccid_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max)
+check_ccid_keypad (int slot, int command, pininfo_t *pininfo)
 {
   unsigned char apdu[] = { 0, 0, 0, 0x81 };
 
   apdu[1] = command;
-  return ccid_transceive_secure (reader_table[slot].ccid.handle,
-                                 apdu, sizeof apdu,
-                                 pin_mode, pinlen_min, pinlen_max,
-                                 NULL, 0, NULL);
+  return ccid_transceive_secure (reader_table[slot].ccid.handle, apdu,
+				 sizeof apdu, pininfo, NULL, 0, NULL);
 }
 
 
 static int
 ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
-		       struct pininfo_s *pininfo)
+		       pininfo_t *pininfo)
 {
   unsigned char apdu[4];
   int err, sw;
@@ -2361,8 +2348,7 @@ ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
   apdu[2] = p0;
   apdu[3] = p1;
   err = ccid_transceive_secure (reader_table[slot].ccid.handle,
-                                apdu, sizeof apdu,
-                                pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                                apdu, sizeof apdu, pininfo,
                                 result, 2, &resultlen);
   if (err)
     return err;
@@ -2580,7 +2566,7 @@ my_rapdu_get_status (int slot, unsigned int *status)
 static int
 my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
                     unsigned char *buffer, size_t *buflen,
-                    struct pininfo_s *pininfo)
+                    pininfo_t *pininfo)
 {
   int err;
   reader_table_t slotp;
@@ -3405,12 +3391,14 @@ apdu_get_status (int slot, int hang,
    the keypad.  Return 0 on success.  For a description of the pin
    parameters, see ccid-driver.c */
 int
-apdu_check_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max)
+apdu_check_keypad (int slot, int command, pininfo_t *pininfo)
 {
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
 
+  if (opt.enable_keypad_varlen)
+    pininfo->mode = 0;
+
   if (reader_table[slot].check_keypad)
     {
       int sw;
@@ -3418,8 +3406,7 @@ apdu_check_keypad (int slot, int command, int pin_mode,
       if ((sw = lock_slot (slot)))
         return sw;
 
-      sw = reader_table[slot].check_keypad (slot, command,
-                                            pin_mode, pinlen_min, pinlen_max);
+      sw = reader_table[slot].check_keypad (slot, command, pininfo);
       unlock_slot (slot);
       return sw;
     }
@@ -3429,15 +3416,9 @@ apdu_check_keypad (int slot, int command, int pin_mode,
 
 
 int
-apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
-                    int pinlen_min, int pinlen_max)
+apdu_keypad_verify (int slot, int class, int ins, int p0, int p1,
+		    pininfo_t *pininfo)
 {
-  struct pininfo_s pininfo;
-
-  pininfo.mode = pin_mode;
-  pininfo.minlen = pinlen_min;
-  pininfo.maxlen = pinlen_max;
-
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
 
@@ -3449,7 +3430,7 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
         return sw;
 
       sw = reader_table[slot].keypad_verify (slot, class, ins, p0, p1,
-                                             &pininfo);
+					     pininfo);
       unlock_slot (slot);
       return sw;
     }
@@ -3459,15 +3440,9 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
 
 
 int
-apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
-                    int pinlen_min, int pinlen_max)
+apdu_keypad_modify (int slot, int class, int ins, int p0, int p1,
+		    pininfo_t *pininfo)
 {
-  struct pininfo_s pininfo;
-
-  pininfo.mode = pin_mode;
-  pininfo.minlen = pinlen_min;
-  pininfo.maxlen = pinlen_max;
-
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
 
@@ -3479,7 +3454,7 @@ apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
         return sw;
 
       sw = reader_table[slot].keypad_modify (slot, class, ins, p0, p1,
-                                             &pininfo);
+                                             pininfo);
       unlock_slot (slot);
       return sw;
     }
@@ -3492,7 +3467,7 @@ apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
    function should be called in locked state. */
 static int
 send_apdu (int slot, unsigned char *apdu, size_t apdulen,
-           unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
+           unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
 {
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -3524,7 +3499,7 @@ static int
 send_le (int slot, int class, int ins, int p0, int p1,
          int lc, const char *data, int le,
          unsigned char **retbuf, size_t *retbuflen,
-         struct pininfo_s *pininfo, int extended_mode)
+         pininfo_t *pininfo, int extended_mode)
 {
 #define SHORT_RESULT_BUFFER_SIZE 258
   /* We allocate 8 extra bytes as a safety margin towards a driver bug.  */
diff --git a/scd/apdu.h b/scd/apdu.h
index 6bf6176..c69fe36 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -114,12 +114,11 @@ int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
 int apdu_reset (int slot);
 int apdu_get_status (int slot, int hang,
                      unsigned int *status, unsigned int *changed);
-int apdu_check_keypad (int slot, int command, int pin_mode,
-                       int pinlen_min, int pinlen_max);
+int apdu_check_keypad (int slot, int command, pininfo_t *pininfo);
 int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1,
-                        int pin_mode, int pinlen_min, int pinlen_max);
+			pininfo_t *pininfo);
 int apdu_keypad_modify (int slot, int class, int ins, int p0, int p1,
-                        int pin_mode, int pinlen_min, int pinlen_max);
+			pininfo_t *pininfo);
 int apdu_send_simple (int slot, int extended_mode,
                       int class, int ins, int p0, int p1,
                       int lc, const char *data);
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index 50db78e..f3f7d4b 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -282,7 +282,7 @@ verify_pin (app_t app,
 {
   const char *s;
   int rc;
-  iso7816_pininfo_t pininfo;
+  pininfo_t pininfo;
 
   if ( app->did_chv1 && !app->force_chv1 )
     return 0;  /* No need to verify it again.  */
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 28ccb9a..4e7a43c 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -781,7 +781,7 @@ verify_pin (app_t app, int pwid, const char *desc,
             gpg_error_t (*pincb)(void*, const char *, char **),
             void *pincb_arg)
 {
-  iso7816_pininfo_t pininfo;
+  pininfo_t pininfo;
   int rc;
 
   if (!desc)
@@ -1144,7 +1144,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *pwidstr,
   int is_sigg;
   const char *newdesc;
   int pwid;
-  iso7816_pininfo_t pininfo;
+  pininfo_t pininfo;
 
   (void)ctrl;
 
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 5928ec6..968ef98 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1489,7 +1489,7 @@ verify_a_chv (app_t app,
   int rc = 0;
   char *prompt_buffer = NULL;
   const char *prompt;
-  iso7816_pininfo_t pininfo;
+  pininfo_t pininfo;
   int minlen = 6;
 
   assert (chvno == 1 || chvno == 2);
@@ -1707,7 +1707,7 @@ verify_chv3 (app_t app,
 
   if (!app->did_chv3)
     {
-      iso7816_pininfo_t pininfo;
+      pininfo_t pininfo;
       int minlen = 8;
       char *prompt;
 
@@ -1917,7 +1917,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
   char *pinvalue = NULL;
   int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
   int set_resetcode = 0;
-  iso7816_pininfo_t pininfo;
+  pininfo_t pininfo;
   int use_keypad = 0;
   int minlen = 6;
 
diff --git a/scd/app.c b/scd/app.c
index dfb5991..e6a663e 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -26,8 +26,8 @@
 
 #include "scdaemon.h"
 #include "app-common.h"
-#include "apdu.h"
 #include "iso7816.h"
+#include "apdu.h"
 #include "tlv.h"
 
 /* This table is used to keep track of locks on a per reader base.
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 710d0e2..c16c7ac 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -89,6 +89,8 @@
 
 #include <usb.h>
 
+#include "scdaemon.h"
+#include "iso7816.h"
 #include "ccid-driver.h"
 
 #define DRVNAME "ccid-driver: "
@@ -3296,7 +3298,7 @@ ccid_transceive (ccid_driver_t handle,
 int
 ccid_transceive_secure (ccid_driver_t handle,
                         const unsigned char *apdu_buf, size_t apdu_buflen,
-                        int pin_mode, int pinlen_min, int pinlen_max,
+			pininfo_t *pininfo,
                         unsigned char *resp, size_t maxresplen, size_t *nresp)
 {
   int rc;
@@ -3307,7 +3309,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   size_t dummy_nresp;
   int testmode;
   int cherry_mode = 0;
-  int enable_varlen = opt.enable_keypad_varlen;
+  int enable_varlen = 0;
 
   testmode = !resp && !nresp;
 
@@ -3322,18 +3324,15 @@ ccid_transceive_secure (ccid_driver_t handle,
   else
     return CCID_DRIVER_ERR_NO_KEYPAD;
 
-  if (pin_mode != 1)
-    return CCID_DRIVER_ERR_NOT_SUPPORTED;
-
-  if (!pinlen_min)
-    pinlen_min = 1;
-  if (!pinlen_max)
-    pinlen_max = 25;
+  if (!pininfo->minlen)
+    pininfo->minlen = 1;
+  if (!pininfo->maxlen)
+    pininfo->maxlen = 25;
 
   /* Note that the 25 is the maximum value the SPR532 allows.  */
-  if (pinlen_min < 1 || pinlen_min > 25
-      || pinlen_max < 1 || pinlen_max > 25
-      || pinlen_min > pinlen_max)
+  if (pininfo->minlen < 1 || pininfo->minlen > 25
+      || pininfo->maxlen < 1 || pininfo->maxlen > 25
+      || pininfo->minlen > pininfo->maxlen)
     return CCID_DRIVER_ERR_INV_VALUE;
 
   /* We have only tested a few readers so better don't risk anything
@@ -3347,7 +3346,7 @@ ccid_transceive_secure (ccid_driver_t handle,
       break;
     case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
       enable_varlen = 1;
-      pinlen_max = 15;
+      pininfo->maxlen = 15;
       break;
     case VENDOR_CHERRY:
       enable_varlen = 1;
@@ -3370,6 +3369,12 @@ ccid_transceive_secure (ccid_driver_t handle,
      return CCID_DRIVER_ERR_NOT_SUPPORTED;
     }
 
+  if (enable_varlen)
+    pininfo->mode = 0;
+
+  if (pininfo->mode != 0 && pininfo->mode != 1)
+    return CCID_DRIVER_ERR_NOT_SUPPORTED;
+
   if (testmode)
     return 0; /* Success */
 
@@ -3417,8 +3422,8 @@ ccid_transceive_secure (ccid_driver_t handle,
     }
 
   /* The following is a little endian word. */
-  msg[msglen++] = pinlen_max;   /* wPINMaxExtraDigit-Maximum.  */
-  msg[msglen++] = pinlen_min;   /* wPINMaxExtraDigit-Minimum.  */
+  msg[msglen++] = pininfo->maxlen;   /* wPINMaxExtraDigit-Maximum.  */
+  msg[msglen++] = pininfo->minlen;   /* wPINMaxExtraDigit-Minimum.  */
 
   if (apdu_buf[1] == 0x24)
     msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01;
@@ -3431,7 +3436,7 @@ ccid_transceive_secure (ccid_driver_t handle,
 
   msg[msglen] = 0x02; /* bEntryValidationCondition:
                          Validation key pressed */
-  if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
+  if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
     msg[msglen] |= 0x01; /* Max size reached.  */
   msglen++;
 
diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h
index e0f4895..217bb72 100644
--- a/scd/ccid-driver.h
+++ b/scd/ccid-driver.h
@@ -93,8 +93,7 @@ int ccid_transceive (ccid_driver_t handle,
                      unsigned char *resp, size_t maxresplen, size_t *nresp);
 int ccid_transceive_secure (ccid_driver_t handle,
                      const unsigned char *apdu, size_t apdulen,
-                     int pin_mode,
-                     int pinlen_min, int pinlen_max,
+		     pininfo_t *pininfo,
                      unsigned char *resp, size_t maxresplen, size_t *nresp);
 int ccid_transceive_escape (ccid_driver_t handle,
                             const unsigned char *data, size_t datalen,
diff --git a/scd/command.c b/scd/command.c
index 40e61a4..343830a 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -34,6 +34,7 @@
 #include <assuan.h>
 #include <ksba.h>
 #include "app-common.h"
+#include "iso7816.h"
 #include "apdu.h" /* Required for apdu_*_reader (). */
 #include "atr.h"
 #include "exechelp.h"
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 966a741..b2324b4 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -269,12 +269,11 @@ iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
 /* Check whether the reader supports the ISO command code COMMAND on
    the keypad.  Returns 0 on success.  */
 gpg_error_t
-iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
+iso7816_check_keypad (int slot, int command, pininfo_t *pininfo)
 {
   int sw;
 
-  sw = apdu_check_keypad (slot, command,
-                          pininfo->mode, pininfo->minlen, pininfo->maxlen);
+  sw = apdu_check_keypad (slot, command, pininfo);
   return iso7816_map_sw (sw);
 }
 
@@ -283,12 +282,11 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
    vector CHVNO.  With PININFO non-NULL the keypad of the reader will
    be used.  Returns 0 on success. */
 gpg_error_t
-iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
+iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo)
 {
   int sw;
 
-  sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
-                           pininfo->mode, pininfo->minlen, pininfo->maxlen);
+  sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, pininfo);
   return map_sw (sw);
 }
 
@@ -309,14 +307,12 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
    data" is done, otherwise an "exchange reference data".  */
 gpg_error_t
 iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
-                                  iso7816_pininfo_t *pininfo)
+                                  pininfo_t *pininfo)
 {
   int sw;
 
   sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
-			   is_exchange ? 1 : 0,
-			   chvno, pininfo->mode, pininfo->minlen,
-			   pininfo->maxlen);
+			   is_exchange ? 1 : 0, chvno, pininfo);
   return map_sw (sw);
 }
 
diff --git a/scd/iso7816.h b/scd/iso7816.h
index a4e5b70..e6dfecd 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -32,13 +32,13 @@
 
 /* Information to be passed to keypad equipped readers.  See
    ccid-driver.c for details. */
-struct iso7816_pininfo_s
+struct pininfo_s
 {
-  int mode;    /* A mode of 0 means: Do not use the keypad. */
+  int mode;    /* 0: Use variable length input.  1: Use fixed length input. */
   int minlen;
   int maxlen;
 };
-typedef struct iso7816_pininfo_s iso7816_pininfo_t;
+typedef struct pininfo_s pininfo_t;
 
 
 gpg_error_t iso7816_map_sw (int sw);
@@ -58,16 +58,16 @@ gpg_error_t iso7816_apdu_direct (int slot,
                                  int handle_more,
                                  unsigned char **result, size_t *resultlen);
 gpg_error_t iso7816_check_keypad (int slot, int command,
-                                  iso7816_pininfo_t *pininfo);
+                                  pininfo_t *pininfo);
 gpg_error_t iso7816_verify (int slot,
                             int chvno, const char *chv, size_t chvlen);
-gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo);
+gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
 gpg_error_t iso7816_change_reference_data (int slot, int chvno,
                                const char *oldchv, size_t oldchvlen,
                                const char *newchv, size_t newchvlen);
 gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
 					      int is_exchange,
-                                              iso7816_pininfo_t *pininfo);
+                                              pininfo_t *pininfo);
 gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
                                          const char *newchv, size_t newchvlen);
 gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c
index 3f34d69..e503d36 100644
--- a/scd/sc-copykeys.c
+++ b/scd/sc-copykeys.c
@@ -33,6 +33,7 @@
 
 #include "../common/ttyio.h"
 #include "../common/simple-pwquery.h"
+#include "iso7816.h"
 #include "apdu.h" /* for open_reader */
 #include "atr.h"
 #include "app-common.h"
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index 1b61894..f8a86c8 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -48,6 +48,7 @@
 #include "i18n.h"
 #include "sysutils.h"
 #include "app-common.h"
+#include "iso7816.h"
 #include "apdu.h"
 #include "ccid-driver.h"
 #include "mkdtemp.h"

commit ca89277cb4cb9558da97a71a4cb070cb77c9b536
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Mon Jan 7 14:20:55 2013 +0900

    SCD: Clean up.  Remove PADLEN for keypad input.
    
    * scd/apdu.c (struct pininfo_s): Use iso7816_pininfo_s.
    (struct reader_table_s): Remove last arg from check_keypad method.
    (check_pcsc_keypad, check_pcsc_keypad): Remove PIN_PADLEN.
    (pcsc_keypad_verify, pcsc_keypad_modify): Don't check PIN_PADLEN.
    (send_apdu_ccid, ccid_keypad_operation): Remove PIN_PADLEN.
    (apdu_check_keypad, apdu_keypad_verify, apdu_keypad_modify):
    Likewise.
    
    * scd/apdu.h (apdu_check_keypad, apdu_keypad_verify)
    (apdu_keypad_modify): Remove PIN_PADLEN.
    
    * scd/ccid-driver.c (ccid_transceive_secure): Remove PIN_PADLEN.
    
    * scd/ccid-driver.h (ccid_transceive_secure): Remove PIN_PADLEN.
    
    * scd/iso7816.c (iso7816_check_keypad, iso7816_verify_kp)
    (iso7816_change_reference_data_kp): Remove PADLEN.
    
    * scd/iso7816.h (struct iso7816_pininfo_s): Remove PADLEN, PADCHAR.
    --
    In the OpenPGPcard specification, password comes with no padding.  In
    GnuPG, we support keypad input for OpenPGPcard only.  Thus, it is
    useless to try to support padding for keypad input.

diff --git a/scd/apdu.c b/scd/apdu.c
index 278e08a..f66db4d 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -83,15 +83,7 @@
 #define DLSTDCALL
 #endif
 
-
-/* Helper to pass parameters related to keypad based operations. */
-struct pininfo_s
-{
-  int mode;
-  int minlen;
-  int maxlen;
-  int padlen;
-};
+#define pininfo_s iso7816_pininfo_s
 
 /* A structure to collect information pertaining to one reader
    slot. */
@@ -108,7 +100,7 @@ struct reader_table_s {
   int (*get_status_reader)(int, unsigned int *);
   int (*send_apdu_reader)(int,unsigned char *,size_t,
                           unsigned char *, size_t *, struct pininfo_s *);
-  int (*check_keypad)(int, int, int, int, int, int);
+  int (*check_keypad)(int, int, int, int, int);
   void (*dump_status_reader)(int);
   int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
   int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *);
@@ -331,7 +323,7 @@ static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
                                      unsigned int *status,
                                      unsigned int *changed);
 static int check_pcsc_keypad (int slot, int command, int pin_mode,
-                              int pinlen_min, int pinlen_max, int pin_padlen);
+                              int pinlen_min, int pinlen_max);
 static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
                                struct pininfo_s *pininfo);
 static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
@@ -1993,7 +1985,7 @@ open_pcsc_reader (const char *portstr)
    on the keypad.  Return 0 on success.  */
 static int
 check_pcsc_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max, int pin_padlen)
+                   int pinlen_min, int pinlen_max)
 {
   unsigned char buf[256];
   size_t len = 256;
@@ -2002,7 +1994,6 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
   (void)pin_mode;
   (void)pinlen_min;
   (void)pinlen_max;
-  (void)pin_padlen;
 
  check_again:
   if (command == ISO7816_VERIFY)
@@ -2069,9 +2060,6 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   if (pininfo->mode != 1)
     return SW_NOT_SUPPORTED;
 
-  if (pininfo->padlen != 0)
-    return SW_NOT_SUPPORTED;
-
   if (!pininfo->minlen)
     pininfo->minlen = 1;
   if (!pininfo->maxlen)
@@ -2153,9 +2141,6 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   if (pininfo->mode != 1)
     return SW_NOT_SUPPORTED;
 
-  if (pininfo->padlen != 0)
-    return SW_NOT_SUPPORTED;
-
   if (!pininfo->minlen)
     pininfo->minlen = 1;
   if (!pininfo->maxlen)
@@ -2332,7 +2317,6 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
                                   pininfo->mode,
                                   pininfo->minlen,
                                   pininfo->maxlen,
-                                  pininfo->padlen,
                                   buffer, maxbuflen, buflen);
   else
     err = ccid_transceive (reader_table[slot].ccid.handle,
@@ -2351,14 +2335,14 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
    parameters, see ccid-driver.c */
 static int
 check_ccid_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max, int pin_padlen)
+                   int pinlen_min, int pinlen_max)
 {
   unsigned char apdu[] = { 0, 0, 0, 0x81 };
 
   apdu[1] = command;
   return ccid_transceive_secure (reader_table[slot].ccid.handle,
                                  apdu, sizeof apdu,
-                                 pin_mode, pinlen_min, pinlen_max, pin_padlen,
+                                 pin_mode, pinlen_min, pinlen_max,
                                  NULL, 0, NULL);
 }
 
@@ -2379,7 +2363,6 @@ ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
   err = ccid_transceive_secure (reader_table[slot].ccid.handle,
                                 apdu, sizeof apdu,
                                 pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                                pininfo->padlen,
                                 result, 2, &resultlen);
   if (err)
     return err;
@@ -3423,7 +3406,7 @@ apdu_get_status (int slot, int hang,
    parameters, see ccid-driver.c */
 int
 apdu_check_keypad (int slot, int command, int pin_mode,
-                   int pinlen_min, int pinlen_max, int pin_padlen)
+                   int pinlen_min, int pinlen_max)
 {
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -3436,8 +3419,7 @@ apdu_check_keypad (int slot, int command, int pin_mode,
         return sw;
 
       sw = reader_table[slot].check_keypad (slot, command,
-                                            pin_mode, pinlen_min, pinlen_max,
-                                            pin_padlen);
+                                            pin_mode, pinlen_min, pinlen_max);
       unlock_slot (slot);
       return sw;
     }
@@ -3448,14 +3430,13 @@ apdu_check_keypad (int slot, int command, int pin_mode,
 
 int
 apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
-                    int pinlen_min, int pinlen_max, int pin_padlen)
+                    int pinlen_min, int pinlen_max)
 {
   struct pininfo_s pininfo;
 
   pininfo.mode = pin_mode;
   pininfo.minlen = pinlen_min;
   pininfo.maxlen = pinlen_max;
-  pininfo.padlen = pin_padlen;
 
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
@@ -3479,14 +3460,13 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
 
 int
 apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
-                    int pinlen_min, int pinlen_max, int pin_padlen)
+                    int pinlen_min, int pinlen_max)
 {
   struct pininfo_s pininfo;
 
   pininfo.mode = pin_mode;
   pininfo.minlen = pinlen_min;
   pininfo.maxlen = pinlen_max;
-  pininfo.padlen = pin_padlen;
 
   if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
     return SW_HOST_NO_DRIVER;
diff --git a/scd/apdu.h b/scd/apdu.h
index bf55346..6bf6176 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -115,13 +115,11 @@ int apdu_reset (int slot);
 int apdu_get_status (int slot, int hang,
                      unsigned int *status, unsigned int *changed);
 int apdu_check_keypad (int slot, int command, int pin_mode,
-                       int pinlen_min, int pinlen_max, int pin_padlen);
+                       int pinlen_min, int pinlen_max);
 int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1,
-                        int pin_mode, int pinlen_min, int pinlen_max,
-                        int pin_padlen);
+                        int pin_mode, int pinlen_min, int pinlen_max);
 int apdu_keypad_modify (int slot, int class, int ins, int p0, int p1,
-                        int pin_mode, int pinlen_min, int pinlen_max,
-                        int pin_padlen);
+                        int pin_mode, int pinlen_min, int pinlen_max);
 int apdu_send_simple (int slot, int extended_mode,
                       int class, int ins, int p0, int p1,
                       int lc, const char *data);
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index f545c71..710d0e2 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -3288,7 +3288,7 @@ ccid_transceive (ccid_driver_t handle,
           The APDU should me made up of 4 bytes without Lc.
 
    PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
-   may be used t enable reasonable defaults.  PIN_PADLEN should be 0.
+   may be used t enable reasonable defaults.
 
    When called with RESP and NRESP set to NULL, the function will
    merely check whether the reader supports the secure command for the
@@ -3297,7 +3297,6 @@ int
 ccid_transceive_secure (ccid_driver_t handle,
                         const unsigned char *apdu_buf, size_t apdu_buflen,
                         int pin_mode, int pinlen_min, int pinlen_max,
-                        int pin_padlen,
                         unsigned char *resp, size_t maxresplen, size_t *nresp)
 {
   int rc;
@@ -3326,9 +3325,6 @@ ccid_transceive_secure (ccid_driver_t handle,
   if (pin_mode != 1)
     return CCID_DRIVER_ERR_NOT_SUPPORTED;
 
-  if (pin_padlen != 0)
-    return CCID_DRIVER_ERR_NOT_SUPPORTED;
-
   if (!pinlen_min)
     pinlen_min = 1;
   if (!pinlen_max)
diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h
index 121cb94..e0f4895 100644
--- a/scd/ccid-driver.h
+++ b/scd/ccid-driver.h
@@ -94,7 +94,7 @@ int ccid_transceive (ccid_driver_t handle,
 int ccid_transceive_secure (ccid_driver_t handle,
                      const unsigned char *apdu, size_t apdulen,
                      int pin_mode,
-                     int pinlen_min, int pinlen_max, int pin_padlen,
+                     int pinlen_min, int pinlen_max,
                      unsigned char *resp, size_t maxresplen, size_t *nresp);
 int ccid_transceive_escape (ccid_driver_t handle,
                             const unsigned char *data, size_t datalen,
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 45f5e08..966a741 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -274,8 +274,7 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
   int sw;
 
   sw = apdu_check_keypad (slot, command,
-                          pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                          pininfo->padlen);
+                          pininfo->mode, pininfo->minlen, pininfo->maxlen);
   return iso7816_map_sw (sw);
 }
 
@@ -289,8 +288,7 @@ iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
   int sw;
 
   sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
-                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
-                           pininfo->padlen);
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen);
   return map_sw (sw);
 }
 
@@ -318,7 +316,7 @@ iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
   sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
 			   is_exchange ? 1 : 0,
 			   chvno, pininfo->mode, pininfo->minlen,
-			   pininfo->maxlen, pininfo->padlen);
+			   pininfo->maxlen);
   return map_sw (sw);
 }
 
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 336208a..a4e5b70 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -37,8 +37,6 @@ struct iso7816_pininfo_s
   int mode;    /* A mode of 0 means: Do not use the keypad. */
   int minlen;
   int maxlen;
-  int padlen;
-  int padchar;
 };
 typedef struct iso7816_pininfo_s iso7816_pininfo_t;
 

commit d9f6cc7502793ed41928042cc2f968c8c7effc22
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Wed Jan 9 13:24:57 2013 +0900

    SCD: Add option enable-keypad-varlen and support for GEMPC_PINPAD.
    
    * scd/scdaemon.h (opt): Add enable_keypad_varlen.
    * scd/scdaemon.c (cmd_and_opt_values): Add oEnableKeypadVarlen.
    (opts, main): Add oEnableKeypadVarlen.
    * scd/ccid-driver.c (GEMPC_PINPAD): New.
    (ccid_transceive_secure): Add enable_varlen handling.
    Enable GEMPC_PINPAD.
    --
    Note that GEMPC_PINPAD doesn't support variable length keypad input.
    The feature of fixed length keypad input will be added soon.

diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 5b3bcaf..f545c71 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -220,6 +220,7 @@ enum {
 #define SCM_SPR532      0xe003
 #define CHERRY_ST2000   0x003e
 #define VASCO_920       0x0920
+#define GEMPC_PINPAD	0x3478
 
 /* A list and a table with special transport descriptions. */
 enum {
@@ -3307,6 +3308,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   size_t dummy_nresp;
   int testmode;
   int cherry_mode = 0;
+  int enable_varlen = opt.enable_keypad_varlen;
 
   testmode = !resp && !nresp;
 
@@ -3345,11 +3347,14 @@ ccid_transceive_secure (ccid_driver_t handle,
     case VENDOR_SCM:  /* Tested with SPR 532. */
     case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
     case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05).  */
+      enable_varlen = 1;
       break;
     case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
+      enable_varlen = 1;
       pinlen_max = 15;
       break;
     case VENDOR_CHERRY:
+      enable_varlen = 1;
       /* The CHERRY XX44 keyboard echos an asterisk for each entered
          character on the keyboard channel.  We use a special variant
          of PC_to_RDR_Secure which directs these characters to the
@@ -3360,6 +3365,11 @@ ccid_transceive_secure (ccid_driver_t handle,
       if (handle->id_product != CHERRY_ST2000)
         cherry_mode = 1;
       break;
+    case VENDOR_GEMPC:
+      enable_varlen = 0;
+      if (handle->id_product == GEMPC_PINPAD)
+	break;
+      /* fall through */
     default:
      return CCID_DRIVER_ERR_NOT_SUPPORTED;
     }
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index af4c9c1..1b61894 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -95,6 +95,7 @@ enum cmd_and_opt_values
   oAllowAdmin,
   oDenyAdmin,
   oDisableApplication,
+  oEnableKeypadVarlen,
   oDebugDisableTicker
 };
 
@@ -148,6 +149,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oDenyAdmin, "deny-admin",
                 N_("deny the use of admin card commands")),
   ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
+  ARGPARSE_s_n (oEnableKeypadVarlen, "enable-keypad-varlen",
+                N_("use variable length input for keypad")),
 
   ARGPARSE_end ()
 };
@@ -587,6 +590,8 @@ main (int argc, char **argv )
           add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
           break;
 
+	case oEnableKeypadVarlen: opt.enable_keypad_varlen = 1; break;
+
         default:
           pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
           break;
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 74e8b7d..8f048d5 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -57,6 +57,7 @@ struct
   const char *reader_port;  /* NULL or reder port to use. */
   int disable_ccid;    /* Disable the use of the internal CCID driver. */
   int disable_keypad;  /* Do not use a keypad. */
+  int enable_keypad_varlen;  /* Use variable length input for keypad. */
   int allow_admin;     /* Allow the use of admin commands for certain
                           cards. */
   strlist_t disabled_applications;  /* Card applications we do not

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

Summary of changes:
 scd/apdu.c        |  149 +++++++++++-------------------
 scd/apdu.h        |    9 +-
 scd/app-dinsig.c  |    4 +-
 scd/app-nks.c     |    6 +-
 scd/app-openpgp.c |  122 ++++++++++++++++++++++---
 scd/app.c         |    2 +-
 scd/ccid-driver.c |  270 ++++++++++++++++++++++++++++++++---------------------
 scd/ccid-driver.h |    3 +-
 scd/command.c     |    1 +
 scd/iso7816.c     |   18 +---
 scd/iso7816.h     |   19 ++--
 scd/sc-copykeys.c |    1 +
 scd/scdaemon.c    |    6 +
 scd/scdaemon.h    |    1 +
 14 files changed, 365 insertions(+), 246 deletions(-)


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




More information about the Gnupg-commits mailing list