pcsc pinpad support (part 6)

NIIBE Yutaka gniibe at fsij.org
Fri Feb 4 07:26:31 CET 2011


Yes, the patch series is still on going.

Here is the part 6, adding support of resetting PIN.

It seems for me that CCID protocol doesn't assume that the command
PUT_DATA will be issued by PC_to_RDR_Secure message.  So, this code
doesn't support setting the reset code by keypad (even if it would
be possible).


2011-02-04  NIIBE Yutaka  <gniibe at fsij.org>

	* iso7816.c (iso7816_reset_retry_counter_kp): Remove NEWCHV and
	NEWCHVLEN arguments.  Just call apdu_keypad_modify.
	(iso7816_reset_retry_counter_with_rc_kp): New.
	(iso7816_reset_retry_counter): Call apdu_send_simple.

	* app-openpgp.c (do_change_pin): With resetcode, call
	iso7816_reset_retry_counter_with_rc_kp.  With reset_mode, Call
	iso7816_reset_retry_counter_kp.
---
 scd/app-openpgp.c |   86 ++++++++++++++++++++++++++++++++---------------------
 scd/iso7816.c     |   37 +++++++++++++---------
 scd/iso7816.h     |    4 +-
 3 files changed, 76 insertions(+), 51 deletions(-)

diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 18c56f2..547ba15 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -2035,22 +2035,27 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
               goto leave;
             }

-          rc = pincb (pincb_arg,
-                      _("||Please enter the Reset Code for the card"),
-                      &resetcode);
-          if (rc)
-            {
-              log_info (_("PIN callback returned error: %s\n"),
-                        gpg_strerror (rc));
-              goto leave;
-            }
-          if (strlen (resetcode) < minlen)
-            {
-              log_info (_("Reset Code is too short; minimum length is %d\n"),
-                        minlen);
-              rc = gpg_error (GPG_ERR_BAD_PIN);
-              goto leave;
-            }
+	  if (use_keypad)
+	    resetcode = "";	/* Non NULL */
+	  else
+	    {
+	      rc = pincb (pincb_arg,
+			  _("||Please enter the Reset Code for the card"),
+			  &resetcode);
+	      if (rc)
+		{
+		  log_info (_("PIN callback returned error: %s\n"),
+			    gpg_strerror (rc));
+		  goto leave;
+		}
+	      if (strlen (resetcode) < minlen)
+		{
+		  log_info (_("Reset Code is too short; minimum length is %d\n"),
+			    minlen);
+		  rc = gpg_error (GPG_ERR_BAD_PIN);
+		  goto leave;
+		}
+	    }
         }
       else
         {
@@ -2064,7 +2069,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
   else
     app->did_chv1 = app->did_chv2 = 0;

-  if (!use_keypad)
+  if (!use_keypad || set_resetcode)
     {
       /* TRANSLATORS: Do not translate the "|*|" prefixes but
          keep it at the start of the string.  We need this elsewhere
@@ -2083,19 +2088,27 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,

   if (resetcode)
     {
-      char *buffer;
-
-      buffer = xtrymalloc (strlen (resetcode) + strlen (pinvalue) + 1);
-      if (!buffer)
-        rc = gpg_error_from_syserror ();
+      if (use_keypad)
+	{
+	  resetcode = NULL;
+	  rc = iso7816_reset_retry_counter_with_rc_kp (app->slot, 0x81, &pininfo);
+	}
       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)
     {
@@ -2110,11 +2123,16 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr,
     }
   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 = iso7816_reset_retry_counter_kp (app->slot, 0x81, &pininfo);
+      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)
     {
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 117de04..25266a0 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -353,30 +353,30 @@ 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)
 {
   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, 2, 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);
 }


 gpg_error_t
+iso7816_reset_retry_counter_with_rc_kp (int slot, int chvno,
+					iso7816_pininfo_t *pininfo)
+{
+  int sw;
+
+  sw = apdu_keypad_modify (slot, 0x00, CMD_RESET_RETRY_COUNTER, 0, chvno,
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                           pininfo->padlen);
+  return map_sw (sw);
+}
+
+gpg_error_t
 iso7816_reset_retry_counter_with_rc (int slot, int chvno,
                                      const char *data, size_t datalen)
 {
@@ -395,7 +395,14 @@ 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;
+
+  if (!newchv || !newchvlen )
+    return gpg_error (GPG_ERR_INV_VALUE);
+
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_RESET_RETRY_COUNTER,
+                         2, chvno, newchvlen, newchv);
+  return map_sw (sw);
 }


diff --git a/scd/iso7816.h b/scd/iso7816.h
index 6d52702..cac2ca0 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -72,12 +72,12 @@ 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 (int slot, int extended_mode, int tag,
-- 
1.7.2.3



More information about the Gnupg-devel mailing list