[git] GnuPG - branch, master, updated. post-nuke-of-trailing-ws-128-g751d452

by NIIBE Yutaka cvs at cvs.gnupg.org
Tue Nov 29 10:52:06 CET 2011


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  751d452116607eb5ddcbea970b6f24c7a427620e (commit)
       via  5a62b0d6ee7cecc2e41a429ccc586a1a129e1b04 (commit)
       via  57d4f7fae13810f4daed266139c33057de38d114 (commit)
      from  c741c6fc3aaa8b75a434faa143c06dd059970d41 (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 751d452116607eb5ddcbea970b6f24c7a427620e
Merge: 5a62b0d c741c6f
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Nov 29 17:59:56 2011 +0900

    Merge branch 'master' of git+ssh://playfair.gnupg.org/git/gnupg


commit 5a62b0d6ee7cecc2e41a429ccc586a1a129e1b04
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Nov 29 17:56:22 2011 +0900

    PC/SC pinpad support (pinpad input for modify pass phrase with resetcode, by admin).

diff --git a/scd/ChangeLog b/scd/ChangeLog
index 9c11fb3..d0f779e 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,5 +1,27 @@
 2011-11-29  Niibe Yutaka  <gniibe at fsij.org>
 
+	PC/SC pininput support for passphrase modification (2/2)
+	* apdu.h (apdu_send_simple_kp): Remove.
+
+	* apdu.c (pcsc_keypad_modify): Add bConfirmPIN handling.
+	(apdu_send_simple_kp): Remove.
+
+	* iso7816.h (iso7816_reset_retry_counter_kp): Remove arguments
+	of NEWCHV, and NEWCHVLEN.
+	(iso7816_reset_retry_counter_with_rc_kp, iso7816_put_data_kp): New.
+
+	* iso7816.c (iso7816_reset_retry_counter_with_rc_kp): New.
+	(iso7816_reset_retry_counter_kp): Call apdu_keypad_modify.  Only
+	handle the case with PININFO.
+	(iso7816_reset_retry_counter): Don't call
+	iso7816_reset_retry_counter_kp.
+	(iso7816_put_data_kp): New.
+
+	* app-openpgp.c (do_change_pin): Add with_resetcode.
+	Handle keypad for unblocking pass phrase with resetcode,
+	setting up of resetcode, and unblocking by admin.
+
+	PC/SC pininput support for passphrase modification (1/2)
 	* iso7816.h (iso7816_change_reference_data_kp): Remove arguments
 	of OLDCHV, OLDCHVLEN, NEWCHV, and NEWCHVLEN.
 
@@ -23,7 +45,7 @@
 	* iso7816.h (iso7816_verify_kp): Remove arguments of CHV and CHVLEN.
 
 	* iso7816.c (iso7816_verify_kp): Call apdu_keypad_verify. Only
-	handle thecase with PININFO.
+	handle the case with PININFO.
 	(iso7816_verify): Call apdu_send_simple.
 
 	* app-openpgp.c (verify_a_chv, verify_chv3): Follow the change of
diff --git a/scd/apdu.c b/scd/apdu.c
index 380450d..4d11157 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -2125,6 +2125,32 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   unsigned long len = PIN_MODIFY_STRUCTURE_SIZE;
   unsigned char result[2];
   size_t resultlen = 2;
+  unsigned char confirm_pin;
+
+  /* bConfirmPIN
+   *    0x00: new PIN once
+   *    0x01: new PIN twice (confirmation)
+   *    0x02: old PIN and new PIN once
+   *    0x03: old PIN and new PIN twice (confirmation)
+   */
+  switch (ins)
+    {
+    case ISO7816_CHANGE_REFERENCE_DATA:
+      confirm_pin = 0x03;
+      break;
+    case 0xDA:                  /* PUT_DATA */
+      confirm_pin = 0x01;
+      break;
+    case ISO7816_RESET_RETRY_COUNTER:
+      if (p0 == 0)
+        confirm_pin = 0x03;
+      else
+        confirm_pin = 0x01;
+      break;
+    default:
+      confirm_pin = 0x00;
+      break;
+    }
 
   if (!reader_table[slot].atrlen
       && (sw = reset_pcsc_reader (slot)))
@@ -2160,12 +2186,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
   pin_modify[6] = 0x00; /* bInsertionOffsetNew */
   pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
   pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
-  pin_modify[9] = 0x03;  /* bConfirmPIN
-                          *    0x00: new PIN once
-                          *    0x01: new PIN twice (confirmation)
-                          *    0x02: old PIN and new PIN once
-                          *    0x03: old PIN and new PIN twice (confirmation)
-                          */
+  pin_modify[9] = confirm_pin;
   pin_modify[10] = 0x02; /* bEntryValidationCondition: Validation key pressed */
   if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
     pin_modify[10] |= 0x01; /* Max size reached.  */
@@ -3794,24 +3815,6 @@ apdu_send_simple (int slot, int extended_mode,
 }
 
 
-/* Same as apdu_send_simple but uses the keypad of the reader. */
-int
-apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
-                     int lc, const char *data,
-                     int pin_mode,
-                     int pinlen_min, int pinlen_max, int pin_padlen)
-{
-  struct pininfo_s pininfo;
-
-  pininfo.mode = pin_mode;
-  pininfo.minlen = pinlen_min;
-  pininfo.maxlen = pinlen_max;
-  pininfo.padlen = pin_padlen;
-  return send_le (slot, class, ins, p0, p1, lc, data, -1,
-                  NULL, NULL, &pininfo, 0);
-}
-
-
 /* This is a more generic version of the apdu sending routine.  It
    takes an already formatted APDU in APDUDATA or length APDUDATALEN
    and returns with an APDU including the status word.  With
diff --git a/scd/apdu.h b/scd/apdu.h
index e5b4c08..ac1eeeb 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -123,10 +123,6 @@ int apdu_keypad_modify (int slot, int class, int ins, int p0, int p1,
 int apdu_send_simple (int slot, int extended_mode,
                       int class, int ins, int p0, int p1,
                       int lc, const char *data);
-int apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
-                         int lc, const char *data,
-                         int pin_mode,
-                         int pinlen_min, int pinlen_max, int pin_padlen);
 int apdu_send (int slot, int extended_mode,
                int class, int ins, int p0, int p1, int lc, const char *data,
                unsigned char **retbuf, size_t *retbuflen);
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index b3a3ae1..08d641d 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1915,6 +1915,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;
+  int with_resetcode = 0;
   iso7816_pininfo_t pininfo;
   int use_keypad = 0;
   int minlen = 6;
@@ -2024,6 +2025,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
           size_t valuelen;
           int remaining;
 
+          with_resetcode = 1;
           minlen = 8;
           relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
           if (!relptr || valuelen < 7)
@@ -2044,14 +2046,14 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
 
           rc = pincb (pincb_arg,
                       _("||Please enter the Reset Code for the card"),
-                      &resetcode);
+                      use_keypad ? NULL : &resetcode);
           if (rc)
             {
               log_info (_("PIN callback returned error: %s\n"),
                         gpg_strerror (rc));
               goto leave;
             }
-          if (strlen (resetcode) < minlen)
+          if (!use_keypad && strlen (resetcode) < minlen)
             {
               log_info (_("Reset Code is too short; minimum length is %d\n"),
                         minlen);
@@ -2088,40 +2090,65 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
     }
 
 
-  if (resetcode)
+  if (with_resetcode)
     {
-      char *buffer;
-
-      buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1);
-      if (!buffer)
-        rc = gpg_error_from_syserror ();
+      if (use_keypad)
+        {
+          rc = iso7816_reset_retry_counter_with_rc_kp (app->slot, 0x81,
+                                                       &pininfo);
+          pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
+        }
       else
         {
-          strcpy (stpcpy (buffer, resetcode), pinvalue);
-          rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81,
-                                                    buffer, strlen (buffer));
-          wipememory (buffer, strlen (buffer));
-          xfree (buffer);
+          char *buffer;
+
+          buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1);
+          if (!buffer)
+            rc = gpg_error_from_syserror ();
+          else
+            {
+              strcpy (stpcpy (buffer, resetcode), pinvalue);
+              rc = iso7816_reset_retry_counter_with_rc (app->slot, 0x81,
+                                                        buffer, strlen (buffer));
+              wipememory (buffer, strlen (buffer));
+              xfree (buffer);
+            }
         }
     }
   else if (set_resetcode)
     {
-      if (strlen (pinvalue) < 8)
+      if (use_keypad)
         {
-          log_error (_("Reset Code is too short; minimum length is %d\n"), 8);
-          rc = gpg_error (GPG_ERR_BAD_PIN);
+          rc = pincb (pincb_arg,  _("|RN|New Reset Code"), NULL);
+          rc = iso7816_put_data_kp (app->slot, 0xD3, &pininfo);
+          pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
         }
       else
-        rc = iso7816_put_data (app->slot, 0, 0xD3,
-                               pinvalue, strlen (pinvalue));
+        if (strlen (pinvalue) < 8)
+          {
+            log_error (_("Reset Code is too short; minimum length is %d\n"), 8);
+            rc = gpg_error (GPG_ERR_BAD_PIN);
+          }
+        else
+          rc = iso7816_put_data (app->slot, 0, 0xD3,
+                                 pinvalue, strlen (pinvalue));
     }
   else if (reset_mode)
     {
-      rc = iso7816_reset_retry_counter (app->slot, 0x81,
-                                        pinvalue, strlen (pinvalue));
-      if (!rc && !app->app_local->extcap.is_v2)
-        rc = iso7816_reset_retry_counter (app->slot, 0x82,
-                                          pinvalue, strlen (pinvalue));
+      if (use_keypad)
+        {
+          rc = pincb (pincb_arg, _("|N|New PIN"), NULL);
+          rc = iso7816_reset_retry_counter_kp (app->slot, 0x81, &pininfo);
+          pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
+        }
+      else
+        {
+          rc = iso7816_reset_retry_counter (app->slot, 0x81,
+                                            pinvalue, strlen (pinvalue));
+          if (!rc && !app->app_local->extcap.is_v2)
+            rc = iso7816_reset_retry_counter (app->slot, 0x82,
+                                              pinvalue, strlen (pinvalue));
+        }
     }
   else if (!app->app_local->extcap.is_v2)
     {
@@ -2149,8 +2176,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
         {
           rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno,
                                                  &pininfo);
-          /* Dismiss the prompt. */
-          pincb (pincb_arg, NULL, NULL);
+          pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
         }
       else
         rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 8d0f105..8876b93 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -354,26 +354,14 @@ iso7816_change_reference_data (int slot, int chvno,
 
 
 gpg_error_t
-iso7816_reset_retry_counter_kp (int slot, int chvno,
-                                const char *newchv, size_t newchvlen,
-                                iso7816_pininfo_t *pininfo)
+iso7816_reset_retry_counter_with_rc_kp (int slot, int chvno,
+                                        iso7816_pininfo_t *pininfo)
 {
   int sw;
 
-  if (!newchv || !newchvlen )
-    return gpg_error (GPG_ERR_INV_VALUE);
-
-  /* FIXME:  The keypad mode has not yet been tested.  */
-  if (pininfo && pininfo->mode)
-    sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER,
-                           2, chvno, newchvlen, newchv,
-                           pininfo->mode,
-                           pininfo->minlen,
-                           pininfo->maxlen,
+  sw = apdu_keypad_modify (slot, 0x00, CMD_RESET_RETRY_COUNTER, 0, chvno,
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
                            pininfo->padlen);
-  else
-    sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER,
-                           2, chvno, newchvlen, newchv);
   return map_sw (sw);
 }
 
@@ -394,10 +382,27 @@ iso7816_reset_retry_counter_with_rc (int slot, int chvno,
 
 
 gpg_error_t
+iso7816_reset_retry_counter_kp (int slot, int chvno,
+                                iso7816_pininfo_t *pininfo)
+{
+  int sw;
+
+  sw = apdu_keypad_modify (slot, 0x00, CMD_RESET_RETRY_COUNTER, 2, chvno,
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                           pininfo->padlen);
+  return map_sw (sw);
+}
+
+
+gpg_error_t
 iso7816_reset_retry_counter (int slot, int chvno,
                              const char *newchv, size_t newchvlen)
 {
-  return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL);
+  int sw;
+
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER,
+                         2, chvno, newchvlen, newchv);
+  return map_sw (sw);
 }
 
 
@@ -440,6 +445,19 @@ iso7816_get_data (int slot, int extended_mode, int tag,
 }
 
 
+gpg_error_t
+iso7816_put_data_kp  (int slot, int tag, iso7816_pininfo_t *pininfo)
+{
+  int sw;
+
+  sw = apdu_keypad_modify (slot, 0x00, CMD_PUT_DATA,
+                           ((tag >> 8) & 0xff), (tag & 0xff),
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                           pininfo->padlen);
+  return map_sw (sw);
+}
+
+
 /* Perform a PUT DATA command on card in SLOT.  Write DATA of length
    DATALEN to TAG.  EXTENDED_MODE controls whether extended length
    headers or command chaining is used instead of single length
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 5b99e86..9ed7b21 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -72,14 +72,15 @@ gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
 gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
                                          const char *newchv, size_t newchvlen);
 gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno,
-                                            const char *newchv,
-                                            size_t newchvlen,
                                             iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
                                                  const char *data,
                                                  size_t datalen);
+gpg_error_t iso7816_reset_retry_counter_with_rc_kp (int slot, int chvno,
+                                                    iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_get_data (int slot, int extended_mode, int tag,
                               unsigned char **result, size_t *resultlen);
+gpg_error_t iso7816_put_data_kp (int slot, int tag, iso7816_pininfo_t *pininfo);
 gpg_error_t iso7816_put_data (int slot, int extended_mode, int tag,
                               const void *data, size_t datalen);
 gpg_error_t iso7816_put_data_odd (int slot, int extended_mode, int tag,

commit 57d4f7fae13810f4daed266139c33057de38d114
Author: NIIBE Yutaka <gniibe at fsij.org>
Date:   Tue Nov 29 11:59:32 2011 +0900

    PC/SC pinpad support (pinpad input for modify pass phrase).

diff --git a/scd/ChangeLog b/scd/ChangeLog
index 9f991ce..9c11fb3 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,23 @@
+2011-11-29  Niibe Yutaka  <gniibe at fsij.org>
+
+	* iso7816.h (iso7816_change_reference_data_kp): Remove arguments
+	of OLDCHV, OLDCHVLEN, NEWCHV, and NEWCHVLEN.
+
+	* iso7816.c (iso7816_change_reference_data_kp): Call
+	apdu_keypad_modify.
+	(iso7816_change_reference_data): Don't call
+	iso7816_change_reference_data_kp.
+
+	* apdu.h (apdu_keypad_modify): New.
+
+	* apdu.c (pcsc_keypad_modify, apdu_keypad_modify): New.
+	(struct reader_table_s): New memeber function keypad_modify.
+	(new_reader_slot, open_ct_reader, open_ccid_reader)
+	(open_rapdu_reader): Initialize keypad_modify.
+
+	* app-openpgp.c (do_change_pin): Handle keypad and call
+	iso7816_change_reference_data_kp if it is the case.
+
 2011-11-28  Niibe Yutaka  <gniibe at fsij.org>
 
 	* iso7816.h (iso7816_verify_kp): Remove arguments of CHV and CHVLEN.
diff --git a/scd/apdu.c b/scd/apdu.c
index 866ebb9..380450d 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -112,6 +112,7 @@ struct reader_table_s {
   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 *);
 
   struct {
     ccid_driver_t handle;
@@ -335,6 +336,8 @@ static int check_pcsc_keypad (int slot, int command, int pin_mode,
                               int pinlen_min, int pinlen_max, int pin_padlen);
 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,
+                               struct pininfo_s *pininfo);
 
 
 
@@ -382,6 +385,7 @@ new_reader_slot (void)
   reader_table[reader].dump_status_reader = NULL;
   reader_table[reader].set_progress_cb = NULL;
   reader_table[reader].keypad_verify = pcsc_keypad_verify;
+  reader_table[reader].keypad_modify = pcsc_keypad_modify;
 
   reader_table[reader].used = 1;
   reader_table[reader].any_status = 0;
@@ -669,6 +673,7 @@ open_ct_reader (int port)
   reader_table[reader].check_keypad = NULL;
   reader_table[reader].dump_status_reader = ct_dump_reader_status;
   reader_table[reader].keypad_verify = NULL;
+  reader_table[reader].keypad_modify = NULL;
 
   dump_reader_status (reader);
   return reader;
@@ -2108,6 +2113,88 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
   sw = (result[resultlen-2] << 8) | result[resultlen-1];
   return sw;
 }
+
+
+#define PIN_MODIFY_STRUCTURE_SIZE 28
+static int
+pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
+                    struct pininfo_s *pininfo)
+{
+  int sw;
+  unsigned char *pin_modify;
+  unsigned long len = PIN_MODIFY_STRUCTURE_SIZE;
+  unsigned char result[2];
+  size_t resultlen = 2;
+
+  if (!reader_table[slot].atrlen
+      && (sw = reset_pcsc_reader (slot)))
+    return sw;
+
+  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)
+    pininfo->maxlen = 25;
+
+  /* Note that the 25 is the maximum value the SPR532 allows.  */
+  if (pininfo->minlen < 1 || pininfo->minlen > 25
+      || pininfo->maxlen < 1 || pininfo->maxlen > 25
+      || pininfo->minlen > pininfo->maxlen)
+    return SW_HOST_INV_VALUE;
+
+  pin_modify = xtrymalloc (len);
+  if (!pin_modify)
+    return SW_HOST_OUT_OF_CORE;
+
+  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[4] = 0x00; /* bmPINLengthFormat */
+  pin_modify[5] = 0x00; /* bInsertionOffsetOld */
+  pin_modify[6] = 0x00; /* bInsertionOffsetNew */
+  pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
+  pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
+  pin_modify[9] = 0x03;  /* bConfirmPIN
+                          *    0x00: new PIN once
+                          *    0x01: new PIN twice (confirmation)
+                          *    0x02: old PIN and new PIN once
+                          *    0x03: old PIN and new PIN twice (confirmation)
+                          */
+  pin_modify[10] = 0x02; /* bEntryValidationCondition: Validation key pressed */
+  if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
+    pin_modify[10] |= 0x01; /* Max size reached.  */
+  pin_modify[11] = 0xff; /* bNumberMessage: Default */
+  pin_modify[12] =  0x09; /* wLangId: 0x0409: US English */
+  pin_modify[13] = 0x04; /* wLangId: 0x0409: US English */
+  pin_modify[14] = 0x00; /* bMsgIndex1 */
+  pin_modify[15] = 0x00; /* bMsgIndex2 */
+  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[20] = 0x04; /* ulDataLength */
+  pin_modify[21] = 0x00; /* ulDataLength */
+  pin_modify[22] = 0x00; /* ulDataLength */
+  pin_modify[23] = 0x00; /* ulDataLength */
+  pin_modify[24] = class; /* abData[0] */
+  pin_modify[25] = ins; /* abData[1] */
+  pin_modify[26] = p0; /* abData[2] */
+  pin_modify[27] = p1; /* abData[3] */
+
+  sw = control_pcsc (slot, reader_table[slot].pcsc.modify_ioctl,
+                     pin_modify, len, result, &resultlen);
+  xfree (pin_modify);
+  if (sw || resultlen < 2)
+    return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE;
+  sw = (result[resultlen-2] << 8) | result[resultlen-1];
+  return sw;
+}
 
 #ifdef HAVE_LIBUSB
 /*
@@ -2319,6 +2406,7 @@ open_ccid_reader (const char *portstr)
   reader_table[slot].dump_status_reader = dump_ccid_reader_status;
   reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
   reader_table[slot].keypad_verify = ccid_keypad_verify;
+  reader_table[slot].keypad_modify = NULL;
   /* Our CCID reader code does not support T=0 at all, thus reset the
      flag.  */
   reader_table[slot].is_t0 = 0;
@@ -2612,6 +2700,7 @@ open_rapdu_reader (int portno,
   reader_table[slot].check_keypad = NULL;
   reader_table[slot].dump_status_reader = NULL;
   reader_table[slot].keypad_verify = NULL;
+  reader_table[slot].keypad_modify = NULL;
 
   dump_reader_status (slot);
   rapdu_msg_release (msg);
@@ -3250,6 +3339,28 @@ 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)
+{
+  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;
+
+  if (reader_table[slot].keypad_modify)
+    return reader_table[slot].keypad_modify (slot, class, ins, p0, p1,
+                                             &pininfo);
+  else
+    return SW_HOST_NOT_SUPPORTED;
+}
+
+
 /* Dispatcher for the actual send_apdu function. Note, that this
    function should be called in locked state. */
 static int
diff --git a/scd/apdu.h b/scd/apdu.h
index 4dff9eb..e5b4c08 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -117,6 +117,9 @@ int 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 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 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-openpgp.c b/scd/app-openpgp.c
index d7efad5..b3a3ae1 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1912,11 +1912,17 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
   int chvno = atoi (chvnostr);
   char *resetcode = NULL;
   char *oldpinvalue = NULL;
-  char *pinvalue;
+  char *pinvalue = NULL;
   int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
   int set_resetcode = 0;
+  iso7816_pininfo_t pininfo;
+  int use_keypad = 0;
+  int minlen = 6;
 
   (void)ctrl;
+  memset (&pininfo, 0, sizeof pininfo);
+  pininfo.mode = 1;
+  pininfo.minlen = minlen;
 
   if (reset_mode && chvno == 3)
     {
@@ -1960,6 +1966,11 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
     {
       /* Version 2 cards.  */
 
+      if (!opt.disable_keypad
+          && !iso7816_check_keypad (app->slot,
+                                    ISO7816_CHANGE_REFERENCE_DATA, &pininfo))
+        use_keypad = 1;
+
       if (reset_mode)
         {
           /* To reset a PIN the Admin PIN is required. */
@@ -1973,12 +1984,12 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
         }
       else if (chvno == 1 || chvno == 3)
         {
-          int minlen = (chvno ==3)? 8 : 6;
           char *promptbuf = NULL;
           const char *prompt;
 
           if (chvno == 3)
             {
+              minlen = 8;
               rc = build_enter_admin_pin_prompt (app, &promptbuf);
               if (rc)
                 goto leave;
@@ -1986,7 +1997,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
             }
           else
             prompt = _("||Please enter the PIN");
-          rc = pincb (pincb_arg, prompt, &oldpinvalue);
+          rc = pincb (pincb_arg, prompt, use_keypad ? NULL : &oldpinvalue);
           xfree (promptbuf);
           promptbuf = NULL;
           if (rc)
@@ -1996,7 +2007,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
               goto leave;
             }
 
-          if (strlen (oldpinvalue) < minlen)
+          if (!use_keypad && strlen (oldpinvalue) < minlen)
             {
               log_info (_("PIN for CHV%d is too short;"
                           " minimum length is %d\n"), chvno, minlen);
@@ -2012,8 +2023,8 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
           unsigned char *value;
           size_t valuelen;
           int remaining;
-          int minlen = 8;
 
+          minlen = 8;
           relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
           if (!relptr || valuelen < 7)
             {
@@ -2060,17 +2071,20 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
   else
     app->did_chv1 = app->did_chv2 = 0;
 
-  /* TRANSLATORS: Do not translate the "|*|" prefixes but
-     keep it at the start of the string.  We need this elsewhere
-     to get some infos on the string. */
-  rc = pincb (pincb_arg,
-              set_resetcode? _("|RN|New Reset Code") :
-              chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"),
-              &pinvalue);
-  if (rc)
+  if (!use_keypad)
     {
-      log_error (_("error getting new PIN: %s\n"), gpg_strerror (rc));
-      goto leave;
+      /* TRANSLATORS: Do not translate the "|*|" prefixes but
+         keep it at the start of the string.  We need this elsewhere
+         to get some infos on the string. */
+      rc = pincb (pincb_arg,
+                  set_resetcode? _("|RN|New Reset Code") :
+                  chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"),
+                  &pinvalue);
+      if (rc)
+        {
+          log_error (_("error getting new PIN: %s\n"), gpg_strerror (rc));
+          goto leave;
+        }
     }
 
 
@@ -2131,9 +2145,17 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
       /* Version 2 cards.  */
       assert (chvno == 1 || chvno == 3);
 
-      rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
-                                          oldpinvalue, strlen (oldpinvalue),
-                                          pinvalue, strlen (pinvalue));
+      if (use_keypad)
+        {
+          rc = iso7816_change_reference_data_kp (app->slot, 0x80 + chvno,
+                                                 &pininfo);
+          /* Dismiss the prompt. */
+          pincb (pincb_arg, NULL, NULL);
+        }
+      else
+        rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
+                                            oldpinvalue, strlen (oldpinvalue),
+                                            pinvalue, strlen (pinvalue));
     }
 
   if (pinvalue)
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 1238552..8d0f105 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -306,16 +306,29 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
 }
 
 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
+   verification vector CHVNO.  With PININFO non-NULL the keypad of the
+   reader will be used.  */
+gpg_error_t
+iso7816_change_reference_data_kp (int slot, int chvno,
+                                  iso7816_pininfo_t *pininfo)
+{
+  int sw;
+
+  sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, 0, chvno,
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                           pininfo->padlen);
+  return map_sw (sw);
+}
+
+/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
    verification vector CHVNO.  If the OLDCHV is NULL (and OLDCHVLEN
    0), a "change reference data" is done, otherwise an "exchange
    reference data".  The new reference data is expected in NEWCHV of
-   length NEWCHVLEN.  With PININFO non-NULL the keypad of the reader
-   will be used.  */
+   length NEWCHVLEN.  */
 gpg_error_t
-iso7816_change_reference_data_kp (int slot, int chvno,
-                                  const char *oldchv, size_t oldchvlen,
-                                  const char *newchv, size_t newchvlen,
-                                  iso7816_pininfo_t *pininfo)
+iso7816_change_reference_data (int slot, int chvno,
+                               const char *oldchv, size_t oldchvlen,
+                               const char *newchv, size_t newchvlen)
 {
   int sw;
   char *buf;
@@ -332,35 +345,13 @@ iso7816_change_reference_data_kp (int slot, int chvno,
     memcpy (buf, oldchv, oldchvlen);
   memcpy (buf+oldchvlen, newchv, newchvlen);
 
-  if (pininfo && pininfo->mode)
-    sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
-                           oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf,
-                           pininfo->mode,
-                           pininfo->minlen,
-                           pininfo->maxlen,
-                           pininfo->padlen);
-  else
-    sw = apdu_send_simple (slot, 0, 0x00, CMD_CHANGE_REFERENCE_DATA,
-                           oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_CHANGE_REFERENCE_DATA,
+                         oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf);
   xfree (buf);
   return map_sw (sw);
 
 }
 
-/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
-   verification vector CHVNO.  If the OLDCHV is NULL (and OLDCHVLEN
-   0), a "change reference data" is done, otherwise an "exchange
-   reference data".  The new reference data is expected in NEWCHV of
-   length NEWCHVLEN.  */
-gpg_error_t
-iso7816_change_reference_data (int slot, int chvno,
-                               const char *oldchv, size_t oldchvlen,
-                               const char *newchv, size_t newchvlen)
-{
-  return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen,
-                                           newchv, newchvlen, NULL);
-}
-
 
 gpg_error_t
 iso7816_reset_retry_counter_kp (int slot, int chvno,
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 58e81d4..5b99e86 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -68,9 +68,7 @@ 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,
-                               const char *oldchv, size_t oldchvlen,
-                               const char *newchv, size_t newchvlen,
-                               iso7816_pininfo_t *pininfo);
+                                              iso7816_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_kp (int slot, int chvno,

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

Summary of changes:
 scd/ChangeLog     |   44 +++++++++++++++-
 scd/apdu.c        |  150 ++++++++++++++++++++++++++++++++++++++++++++++------
 scd/apdu.h        |    7 +--
 scd/app-openpgp.c |  130 +++++++++++++++++++++++++++++++--------------
 scd/iso7816.c     |  103 ++++++++++++++++++++-----------------
 scd/iso7816.h     |    9 ++--
 6 files changed, 327 insertions(+), 116 deletions(-)


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




More information about the Gnupg-commits mailing list