[PATCH] pcsc pinpad support (part 3)

NIIBE Yutaka gniibe at fsij.org
Fri Jan 14 02:55:27 CET 2011


Here is the part 3.

You can test the feature of pcsc pinpad suport with part 1, part 2 and
part 3.

Before this change, it is layered like following:

	iso7816_verify
        iso7816_verify_kp
	apdu_send_simple, apdu_send_simple_kp
	...

After this change, it will be layered like:

	iso7816_verify      iso7816_verify_kp
        apdu_send_simple    apdu_keypad_verify
	...

and apdu_send_simple_kp will be deprecated.

For PC/SC API, we use SCardControl API to compose CCID
PC_to_RDR_Secure message and SCardTransmit API to compose CCID
PC_to_RDR_XfrBlock message.

Considering the support of PC/SC, we have nothing to share between _kp
version of iso7816_* and no _kp version.  (This will be more clear
when we support change_reference_data.)


2011-01-14  NIIBE Yutaka  <gniibe at fsij.org>

	* apdu.h (apdu_keypad_verify): New.

	* apdu.c (struct reader_table_s): Add keypad_verify.
	(pcsc_keypad_verify): Rename from pcsc_pinpad_verify.
	(ccid_keypad_verify): New.
	(apdu_keypad_verify): New.

	* iso7816.c (iso7816_verify_kp): Call apdu_keypad_verify.  Only
	handle the case with PININFO.
	(iso7816_verify): Call apdu_send_simple.

	* iso7816.h (iso7816_verify_kp): Remove argument of CHV and CHVLEN.

	* app-openpgp.c (verify_a_chv, verify_chv3): Follow the change of
	iso7816_verify_kp.

	* app-dinsig.c (verify_pin): Likewise.

	* app-nks.c (verify_pin): Likewise.

---
 scd/apdu.c        |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 scd/apdu.h        |    3 ++
 scd/app-dinsig.c  |    2 +-
 scd/app-nks.c     |    2 +-
 scd/app-openpgp.c |    4 +-
 scd/iso7816.c     |   23 ++++++++-----------
 scd/iso7816.h     |    4 +--
 7 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/scd/apdu.c b/scd/apdu.c
index bc75dc9..5b7f883 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -110,6 +110,7 @@ struct reader_table_s {
   int (*check_keypad)(int, 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 *);

   struct {
     ccid_driver_t handle;
@@ -328,6 +329,8 @@ static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
                                      unsigned int *changed);
 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);


 
@@ -374,6 +377,7 @@ new_reader_slot (void)
   reader_table[reader].check_keypad = check_pcsc_keypad;
   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].used = 1;
   reader_table[reader].any_status = 0;
@@ -660,6 +664,7 @@ open_ct_reader (int port)
   reader_table[reader].send_apdu_reader = ct_send_apdu;
   reader_table[reader].check_keypad = NULL;
   reader_table[reader].dump_status_reader = ct_dump_reader_status;
+  reader_table[reader].keypad_verify = NULL;

   dump_reader_status (reader);
   return reader;
@@ -2029,7 +2034,7 @@ check_pcsc_keypad (int slot, int command, int pin_mode,

 #define PIN_VERIFY_STRUCTURE_SIZE 23
 static int
-pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
                     struct pininfo_s *pininfo)
 {
   int sw;
@@ -2234,6 +2239,35 @@ check_ccid_keypad (int slot, int command, int pin_mode,
 }


+static int
+ccid_keypad_verify (int slot, int class, int ins, int p0, int p1,
+                    struct pininfo_s *pininfo)
+{
+  unsigned char apdu[4];
+  int err, sw;
+  unsigned char result[2];
+  size_t resultlen = 2;
+
+  apdu[0] = class;
+  apdu[1] = ins;
+  apdu[2] = p0;
+  apdu[3] = 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;
+
+  if (resultlen < 2)
+    return SW_HOST_INCOMPLETE_CARD_RESPONSE;
+
+  sw = (result[resultlen-2] << 8) | result[resultlen-1];
+  return sw;
+}
+
+
 /* Open the reader and try to read an ATR.  */
 static int
 open_ccid_reader (const char *portstr)
@@ -2278,6 +2312,7 @@ open_ccid_reader (const char *portstr)
   reader_table[slot].check_keypad = check_ccid_keypad;
   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;
   /* Our CCID reader code does not support T=0 at all, thus reset the
      flag.  */
   reader_table[slot].is_t0 = 0;
@@ -2570,6 +2605,7 @@ open_rapdu_reader (int portno,
   reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
   reader_table[slot].check_keypad = NULL;
   reader_table[slot].dump_status_reader = NULL;
+  reader_table[slot].keypad_verify = NULL;

   dump_reader_status (slot);
   rapdu_msg_release (msg);
@@ -3165,6 +3201,28 @@ 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)
+{
+  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_verify)
+    return reader_table[slot].keypad_verify (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 c47dea8..4d21fb8 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -114,6 +114,9 @@ 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 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_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 46e9a6a..34fbd13 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -304,7 +304,7 @@ verify_pin (app_t app,
                     gpg_strerror (rc));
           return rc;
         }
-      rc = iso7816_verify_kp (app->slot, 0x81, "", 0, &pininfo);
+      rc = iso7816_verify_kp (app->slot, 0x81, &pininfo);
       /* Dismiss the prompt. */
       pincb (pincb_arg, NULL, NULL);
     }
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 076b913..27a6413 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -803,7 +803,7 @@ verify_pin (app_t app, int pwid, const char *desc,
           return rc;
         }

-      rc = iso7816_verify_kp (app->slot, pwid, "", 0, &pininfo);
+      rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
       pincb (pincb_arg, NULL, NULL);  /* Dismiss the prompt. */
     }
   else
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 029d99f..ac8eacb 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1541,7 +1541,7 @@ verify_a_chv (app_t app,
                     gpg_strerror (rc));
           return rc;
         }
-      rc = iso7816_verify_kp (app->slot, 0x80+chvno, "", 0, &pininfo);
+      rc = iso7816_verify_kp (app->slot, 0x80+chvno, &pininfo);
       /* Dismiss the prompt. */
       pincb (pincb_arg, NULL, NULL);

@@ -1721,7 +1721,7 @@ verify_chv3 (app_t app,
                         gpg_strerror (rc));
               return rc;
             }
-          rc = iso7816_verify_kp (app->slot, 0x83, "", 0, &pininfo);
+          rc = iso7816_verify_kp (app->slot, 0x83, &pininfo);
           /* Dismiss the prompt. */
           pincb (pincb_arg, NULL, NULL);
         }
diff --git a/scd/iso7816.c b/scd/iso7816.c
index b55da41..8490dad 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -281,22 +281,16 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)


 /* Perform a VERIFY command on SLOT using the card holder verification
-   vector CHVNO with a CHV of lenght CHVLEN.  With PININFO non-NULL
-   the keypad of the reader will be used.  Returns 0 on success. */
+   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, const char *chv, size_t chvlen,
-                   iso7816_pininfo_t *pininfo)
+iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
 {
   int sw;

-  if (pininfo && pininfo->mode)
-    sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv,
-                              pininfo->mode,
-                              pininfo->minlen,
-                              pininfo->maxlen,
-                              pininfo->padlen);
-  else
-    sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
+  sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
+                           pininfo->mode, pininfo->minlen, pininfo->maxlen,
+                           pininfo->padlen);
   return map_sw (sw);
 }

@@ -305,7 +299,10 @@ iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen,
 gpg_error_t
 iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
 {
-  return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL);
+  int sw;
+
+  sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
+  return map_sw (sw);
 }

 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 8519712..6af4701 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -63,9 +63,7 @@ gpg_error_t iso7816_check_keypad (int slot, int command,
                                   iso7816_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, const char *chv, size_t chvlen,
-                               iso7816_pininfo_t *pininfo);
+gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_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);
-- 
1.7.2.3




More information about the Gnupg-devel mailing list