SCD: Support fixed length PIN input for keypad.
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 9 Jan 2013 07:23:55 +0000 (16:23 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 5 Feb 2013 04:37:06 +0000 (13:37 +0900)
* 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.

scd/apdu.c
scd/app-dinsig.c
scd/app-nks.c
scd/app-openpgp.c
scd/ccid-driver.c
scd/iso7816.h

index 5a58cfd..a207f9d 100644 (file)
@@ -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)
     {
index f3f7d4b..9d4ebe2 100644 (file)
@@ -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;
 
index 4e7a43c..8a48871 100644 (file)
@@ -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;
 
index 968ef98..dcc3120 100644 (file)
@@ -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)
index c16c7ac..3244c71 100644 (file)
@@ -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);
 
index e6dfecd..bf195ea 100644 (file)
    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;
 };