* app-openpgp.c (do_check_pin): Add hack to allow verification of
authorWerner Koch <wk@gnupg.org>
Mon, 11 Apr 2005 16:20:10 +0000 (16:20 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 11 Apr 2005 16:20:10 +0000 (16:20 +0000)
CHV3.
(get_public_key): Don't use gcry functions to create S-expressions.
(do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for
above change.

scd/ChangeLog
scd/app-openpgp.c
scd/app.c
scd/ccid-driver.c
scd/command.c

index ca73584..f8f8043 100644 (file)
@@ -1,3 +1,11 @@
+2005-04-07  Werner Koch  <wk@g10code.com>
+
+       * app-openpgp.c (do_check_pin): Add hack to allow verification of
+       CHV3.
+       (get_public_key): Don't use gcry functions to create S-expressions.
+       (do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for
+       above change.
+
 2005-03-29  Moritz Schulte  <moritz@g10code.com>
 
        * app-openpgp.c (retrieve_fpr_from_card): New function.
@@ -6,6 +14,19 @@
        (get_public_key): Implement retrival of key through expernal
        helper (gpg) in case the openpgp card is not cooperative enough.
 
+2005-03-16  Werner Koch  <wk@g10code.com>
+
+       * ccid-driver.c (parse_ccid_descriptor): Make SCM workaround
+       reader type specific.
+       (scan_or_find_devices): Do not check the interface subclass in the
+       SPR532 kludge, as this depends on the firmware version.
+       (ccid_get_atr): Get the Slot status first.  This solves the
+       problem with readers hanging on recent Linux 2.6.x.
+       (bulk_in): Add argument TIMEOUT and changed all callers to pass an
+       appropriate one.  Change the standard timeout from 10 to 5 seconds.
+       (ccid_slot_status): Add a retry code with an initial short timeout.
+       (do_close_reader): Do an usb_reset before closing the reader.
+
 2005-02-25  Werner Koch  <wk@g10code.com>
 
        * app-openpgp.c (get_public_key): Make sure not to return negative
        (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) 
        (open_pcsc_reader): Do proper error code mapping.
 
+2005-03-16  Werner Koch  <wk@g10code.com>
+
+       * ccid-driver.c (parse_ccid_descriptor): Make SCM workaround
+       reader type specific.
+       (scan_or_find_devices): Do not check the interface subclass in the
+       SPR532 kludge, as this depends on the firmware version.
+       (ccid_get_atr): Get the Slot status first.  This solves the
+       problem with readers hanging on recent Linux 2.6.x.
+
 2005-02-22  Werner Koch  <wk@g10code.com>
 
        * app-openpgp.c (app_local_s): New field PK.
index bae9dde..1ed0571 100644 (file)
@@ -108,7 +108,14 @@ struct app_local_s {
   struct
   {
     int read_done;   /* True if we have at least tried to read them.  */
-    gcry_sexp_t key; /* Might be NULL if key is not available.  */
+    unsigned char *key; /* This is a malloced buffer with a canonical
+                           encoded S-expression encoding a public
+                           key. Might be NULL if key is not
+                           available.  */
+    size_t keylen;      /* The length of the above S-expression.  Thsi
+                           is usullay only required for corss checks
+                           because the length of an S-expression is
+                           implicitly available.  */
   } pk[3];
 
   /* Keep track of card capabilities.  */
@@ -156,7 +163,7 @@ do_deinit (app_t app)
 
       for (i=0; i < DIM (app->app_local->pk); i++)
         {
-          gcry_sexp_release (app->app_local->pk[i].key);
+          xfree (app->app_local->pk[i].key);
           app->app_local->pk[i].read_done = 0;
         }
       xfree (app->app_local);
@@ -864,6 +871,10 @@ retrieve_key_material (FILE *fp, const char *fpr,
   mpi = NULL;
   ret = 0;
 
+#warning This part should get rewritten for clarity
+  /* We should use an algorithm similar to the one used by gpgme.
+     This will reduce the size of the code at least by 50%.  [wk] */
+
   while (1)
     {
       /* FIXME?  */
@@ -1041,7 +1052,9 @@ retrieve_key_material (FILE *fp, const char *fpr,
    presence of the app->app_local->pk[KEYNO-1].key field.
 
    Note that GnuPG 1.x does not need this and it would be too time
-   consuming to send it just for the fun of it.  */
+   consuming to send it just for the fun of it. However, given that we
+   use the same code in gpg 1.4, we can't use the gcry S-expresion
+   here but need to open encode it. */
 #if GNUPG_MAJOR_VERSION > 1
 static gpg_error_t
 get_public_key (app_t app, int keyno)
@@ -1050,9 +1063,10 @@ get_public_key (app_t app, int keyno)
   unsigned char *buffer;
   const unsigned char *keydata, *m, *e;
   size_t buflen, keydatalen, mlen, elen;
-  gcry_sexp_t sexp;
   unsigned char *mbuf = NULL;
   unsigned char *ebuf = NULL;
+  unsigned char *keybuf = NULL;
+  unsigned char *keybuf_p;
 
   if (keyno < 1 || keyno > 3)
     return gpg_error (GPG_ERR_INV_ID);
@@ -1062,8 +1076,9 @@ get_public_key (app_t app, int keyno)
   if (app->app_local->pk[keyno].read_done)
     return 0;
 
-  gcry_sexp_release (app->app_local->pk[keyno].key);
+  xfree (app->app_local->pk[keyno].key);
   app->app_local->pk[keyno].key = NULL;
+  app->app_local->pk[keyno].keylen = 0;
 
   if (app->card_version > 0x0100)
     {
@@ -1191,16 +1206,29 @@ get_public_key (app_t app, int keyno)
       buffer = NULL;
     }
 
-  err = gcry_sexp_build (&sexp, NULL,
-                        "(public-key (rsa (n %b) (e %b)))",
-                        (int)mlen, m,(int)elen, e);
-  if (err)
+  /* Allocate a buffer to construct the S-expression.  */
+  /* FIXME: We should provide a generalized S-expression creation
+     mechanism. */
+  keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1);
+  if (!keybuf)
     {
-      log_error ("error formatting the key into an S-expression: %s\n",
-                gpg_strerror (err));
+      err = gpg_error_from_errno (errno);
       goto leave;
     }
-  app->app_local->pk[keyno].key = sexp;
+  
+  sprintf (keybuf, "(10:public-key(3:rsa(1:n%u", (unsigned int) mlen);
+  keybuf_p = keybuf + strlen (keybuf);
+  memcpy (keybuf_p, m, mlen);
+  keybuf_p += mlen;
+  sprintf (keybuf_p, ")(1:e%u", (unsigned int)elen);
+  keybuf_p += strlen (keybuf_p);
+  memcpy (keybuf_p, e, elen);
+  keybuf_p += elen;
+  strcpy (keybuf_p, ")))");
+  keybuf_p += strlen (keybuf_p);
+  
+  app->app_local->pk[keyno].key = keybuf;
+  app->app_local->pk[keyno].keylen = (keybuf_p - keybuf);
 
  leave:
   /* Set a flag to indicate that we tried to read the key.  */
@@ -1224,7 +1252,6 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
   /* Note that GnuPG 1.x does not need this and it would be too time
      consuming to send it just for the fun of it. */
 #if GNUPG_MAJOR_VERSION > 1
-  gcry_sexp_t sexp;
   unsigned char grip[20];
   char gripstr[41];
   char idbuf[50];
@@ -1235,15 +1262,14 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
     goto leave;
   
   assert (keyno >= 1 && keyno <= 3);
-  sexp = app->app_local->pk[keyno-1].key;
-  if (!sexp)
-    goto leave; /* No such key.  */
+  if (!app->app_local->pk[keyno-1].key)
+    goto leave; /* No such key - ignore. */
 
-  if (!gcry_pk_get_keygrip (sexp, grip))
-    {
-      err = gpg_error (GPG_ERR_INTERNAL); 
-      goto leave;  
-    }
+  err = keygrip_from_canon_sexp (app->app_local->pk[keyno-1].key,
+                                 app->app_local->pk[keyno-1].keylen,
+                                 grip);
+  if (err)
+    goto leave;
   
   for (i=0; i < 20; i++)
     sprintf (gripstr+i*2, "%02X", grip[i]);
@@ -1303,9 +1329,7 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
 {
   gpg_error_t err;
   int keyno;
-  size_t n;
   unsigned char *buf;
-  gcry_sexp_t sexp;
 
   if (!strcmp (keyid, "OPENPGP.1"))
     keyno = 1;
@@ -1320,24 +1344,11 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
   if (err)
     return err;
 
-  sexp = app->app_local->pk[keyno-1].key;
-  if (!sexp)
-    return gpg_error (GPG_ERR_NO_PUBKEY);
-
-  n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
-  if (!n)
-    return gpg_error (GPG_ERR_BUG);
-  buf = xtrymalloc (n);
+  buf = app->app_local->pk[keyno-1].key;
   if (!buf)
-    return gpg_error_from_errno (errno);
-  n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n);
-  if (!n)
-    {
-      xfree (buf);
-      return gpg_error (GPG_ERR_BUG);
-    }
+    return gpg_error (GPG_ERR_NO_PUBKEY);
   *pk = buf;
-  *pklen = n;
+  *pklen = app->app_local->pk[keyno-1].keylen;;
   return 0;
 }
 
@@ -1590,7 +1601,7 @@ do_change_pin (app_t app, ctrl_t ctrl,  const char *chvnostr, int reset_mode,
   else
     app->did_chv1 = app->did_chv2 = 0;
 
-  /* Note to translators: Do not translate the "|*|" prefixes but
+  /* 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, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), 
@@ -1661,7 +1672,9 @@ do_genkey (app_t app, ctrl_t ctrl,  const char *keynostr, unsigned int flags,
   flush_cache (app);
 
   /* Obviously we need to remove the cached public key.  */
-  gcry_sexp_release (app->app_local->pk[keyno].key);
+  xfree (app->app_local->pk[keyno].key);
+  app->app_local->pk[keyno].key = NULL;
+  app->app_local->pk[keyno].keylen = 0;
   app->app_local->pk[keyno].read_done = 0;
 
   /* Check whether a key already exists.  */
@@ -2142,7 +2155,11 @@ do_decipher (app_t app, const char *keyidstr,
    cheap check on the PIN: If there is something wrong with the PIN
    entry system, only the regular CHV will get blocked and not the
    dangerous CHV3.  KEYIDSTR is the usual card's serial number; an
-   optional fingerprint part will be ignored. */
+   optional fingerprint part will be ignored.
+
+   There is a special mode if the keyidstr is "<serialno>[CHV3]" with
+   the "[CHV3]" being a literal string:  The Admin Pin is checked if
+   and only if the retry counter is still at 3. */
 static int 
 do_check_pin (app_t app, const char *keyidstr,
               int (pincb)(void*, const char *, char **),
@@ -2151,6 +2168,7 @@ do_check_pin (app_t app, const char *keyidstr,
   unsigned char tmp_sn[20]; 
   const char *s;
   int n;
+  int admin_pin = 0;
 
   if (!keyidstr || !*keyidstr)
     return gpg_error (GPG_ERR_INV_VALUE);
@@ -2167,6 +2185,8 @@ do_check_pin (app_t app, const char *keyidstr,
     ; /* No fingerprint given: we allow this for now. */
   else if (*s == '/')
     ; /* We ignore a fingerprint. */
+  else if (!strcmp (s, "[CHV3]") )
+    admin_pin = 1;
   else
     return gpg_error (GPG_ERR_INV_ID);
 
@@ -2177,12 +2197,46 @@ do_check_pin (app_t app, const char *keyidstr,
     return gpg_error (GPG_ERR_INV_CARD);
   if (memcmp (app->serialno, tmp_sn, 16))
     return gpg_error (GPG_ERR_WRONG_CARD);
+
   /* Yes, there is a race conditions: The user might pull the card
      right here and we won't notice that.  However this is not a
      problem and the check above is merely for a graceful failure
      between operations. */
 
-  return verify_chv2 (app, pincb, pincb_arg);
+  if (admin_pin)
+    {
+      void *relptr;
+      unsigned char *value;
+      size_t valuelen;
+      int count;
+      
+      relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
+      if (!relptr || valuelen < 7)
+        {
+          log_error (_("error retrieving CHV status from card\n"));
+          xfree (relptr);
+          return gpg_error (GPG_ERR_CARD);
+        }
+      count = value[6];
+      xfree (relptr);
+
+      if (!count)
+        {
+          log_info (_("card is permanently locked!\n"));
+          return gpg_error (GPG_ERR_BAD_PIN);
+        }
+      else if (value[6] < 3)
+        {
+          log_info (_("verification of Admin PIN is currently prohibited "
+                      "through this command\n"));
+          return gpg_error (GPG_ERR_GENERAL);
+        }
+
+      app->did_chv3 = 0; /* Force verification.  */
+      return verify_chv3 (app, pincb, pincb_arg);
+    }
+  else
+    return verify_chv2 (app, pincb, pincb_arg);
 }
 
 
@@ -2415,7 +2469,9 @@ app_openpgp_storekey (app_t app, int keyno,
 
   flush_cache (app);
 
-  gcry_sexp_release (app->app_local->pk[keyno].key);
+  xfree (app->app_local->pk[keyno].key);
+  app->app_local->pk[keyno].key = NULL;
+  app->app_local->pk[keyno].keylen = 0;
   app->app_local->pk[keyno].read_done = 0;
 
   rc = iso7816_put_data (app->slot,
index 0625dc8..e035e9b 100644 (file)
--- a/scd/app.c
+++ b/scd/app.c
@@ -489,7 +489,7 @@ app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode,
 
 
 /* Perform a VERIFY operation without doing anything lese.  This may
-   be used to initialze a the PION cache for long lasting other
+   be used to initialze a the PIN cache for long lasting other
    operations.  Its use is highly application dependent. */
 int 
 app_check_pin (APP app, const char *keyidstr,
index 4590608..13e11e4 100644 (file)
@@ -1,5 +1,5 @@
 /* ccid-driver.c - USB ChipCardInterfaceDevices driver
- *     Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ *     Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
  *      Written by Werner Koch.
  *
  * This file is part of GnuPG.
@@ -52,7 +52,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $Id$
+ * $Date$
  */
 
 
@@ -223,7 +223,7 @@ static unsigned int compute_edc (const unsigned char *data, size_t datalen,
                                  int use_crc);
 static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen);
 static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
-                    size_t *nread, int expected_type, int seqno);
+                    size_t *nread, int expected_type, int seqno, int timeout);
 
 /* Convert a little endian stored 4 byte value into an unsigned
    integer. */
@@ -446,12 +446,20 @@ parse_ccid_descriptor (ccid_driver_t handle,
      send a frame of n*wMaxPacketSize back to us.  Given that
      wMaxPacketSize is 64 for these readers we set the IFSD to a value
      lower than that:
-        64 - 10 CCID header -  4 T1frame - 2 reserved = 48 */
+        64 - 10 CCID header -  4 T1frame - 2 reserved = 48
+     Product Ids:
+        0xe001 - SCR 331 
+        0x5111 - SCR 331-DI 
+        0x5115 - SCR 335 
+        0xe003 - SPR 532 
+  */
   if (handle->id_vendor == VENDOR_SCM
-      /* FIXME: check whether it is the same
-                firmware version for all drivers.  */
-      && handle->bcd_device < 0x0519
-      && handle->max_ifsd > 48)
+      && handle->max_ifsd > 48      
+      && (  (handle->id_product == 0xe001 && handle->bcd_device < 0x0516)
+          ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620)
+          ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519)
+          ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504)
+          ))
     {
       DEBUGOUT ("enabling workaround for buggy SCM readers\n");
       handle->max_ifsd = 48;
@@ -699,9 +707,7 @@ scan_or_find_devices (int readerno, const char *readerid,
                                   && ifcdesc->bInterfaceProtocol == 0)
                               || (ifcdesc->bInterfaceClass == 255
                                   && dev->descriptor.idVendor == 0x04e6
-                                  && dev->descriptor.idProduct == 0xe003
-                                  && ifcdesc->bInterfaceSubClass == 1
-                                  && ifcdesc->bInterfaceProtocol == 1)))
+                                  && dev->descriptor.idProduct == 0xe003)))
                         {
                           idev = usb_open (dev);
                           if (!idev)
@@ -974,11 +980,13 @@ do_close_reader (ccid_driver_t handle)
       
       rc = bulk_out (handle, msg, msglen);
       if (!rc)
-        bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno);
+        bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
+                 seqno, 2000);
       handle->powered_off = 1;
     }
   if (handle->idev)
     {
+      usb_reset (handle->idev);
       usb_release_interface (handle->idev, handle->ifc_no);
       usb_close (handle->idev);
       handle->idev = NULL;
@@ -1102,10 +1110,10 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen)
    BUFFER and return the actual read number if bytes in NREAD. SEQNO
    is the sequence number used to send the request and EXPECTED_TYPE
    the type of message we expect. Does checks on the ccid
-   header. Returns 0 on success. */
+   header. TIMEOUT is the timeout value in ms. Returns 0 on success. */
 static int
 bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
-         size_t *nread, int expected_type, int seqno)
+         size_t *nread, int expected_type, int seqno, int timeout)
 {
   int i, rc;
   size_t msglen;
@@ -1117,9 +1125,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
   rc = usb_bulk_read (handle->idev, 
                       handle->ep_bulk_in,
                       buffer, length,
-                      10000 /* ms timeout */ );
-  /* Fixme: instead of using a 10 second timeout we should better
-     handle the timeout here and retry if appropriate.  */
+                      timeout);
   if (rc < 0)
     {
       DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno));
@@ -1175,7 +1181,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
 }
 
 
-/* Note that this fucntion won't return the error codes NO_CARD or
+/* Note that this function won't return the error codes NO_CARD or
    CARD_INACTIVE */
 static int 
 send_escape_cmd (ccid_driver_t handle,
@@ -1206,7 +1212,8 @@ send_escape_cmd (ccid_driver_t handle,
   rc = bulk_out (handle, msg, msglen);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape,
+                seqno, 5000);
 
   return rc;
 }
@@ -1276,7 +1283,9 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
   unsigned char msg[100];
   size_t msglen;
   unsigned char seqno;
+  int retries = 0;
 
+ retry:
   msg[0] = PC_to_RDR_GetSlotStatus;
   msg[5] = 0; /* slot */
   msg[6] = seqno = handle->seqno++;
@@ -1288,7 +1297,21 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
   rc = bulk_out (handle, msg, 10);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,
+                seqno, retries? 1000 : 200);
+  if (rc == CCID_DRIVER_ERR_CARD_IO_ERROR && retries < 3)
+    {
+      if (!retries)
+        {
+          fprintf (stderr, "CALLING USB_CLEAR_HALT\n");
+          usb_clear_halt (handle->idev, handle->ep_bulk_in);
+          usb_clear_halt (handle->idev, handle->ep_bulk_out);
+        }
+      else
+          fprintf (stderr, "RETRYING AGIAN\n");
+      retries++;
+      goto retry;
+    }
   if (rc && rc != CCID_DRIVER_ERR_NO_CARD
       && rc != CCID_DRIVER_ERR_CARD_INACTIVE)
     return rc;
@@ -1303,6 +1326,7 @@ ccid_get_atr (ccid_driver_t handle,
               unsigned char *atr, size_t maxatrlen, size_t *atrlen)
 {
   int rc;
+  int statusbits;
   unsigned char msg[100];
   unsigned char *tpdu;
   size_t msglen, tpdulen;
@@ -1311,6 +1335,15 @@ ccid_get_atr (ccid_driver_t handle,
   unsigned int edc;
   int i;
 
+  /* First check whether a card is available.  */
+  rc = ccid_slot_status (handle, &statusbits);
+  if (rc)
+    return rc;
+  if (statusbits == 2)
+    return CCID_DRIVER_ERR_NO_CARD;
+
+  /* For an inactive and also for an active card, issue the PowerOn
+     command to get the ATR.  */
   msg[0] = PC_to_RDR_IccPowerOn;
   msg[5] = 0; /* slot */
   msg[6] = seqno = handle->seqno++;
@@ -1323,7 +1356,8 @@ ccid_get_atr (ccid_driver_t handle,
   rc = bulk_out (handle, msg, msglen);
   if (rc)
     return rc;
-  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno);
+  rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
+                seqno, 5000);
   if (rc)
     return rc;
 
@@ -1367,7 +1401,8 @@ ccid_get_atr (ccid_driver_t handle,
   if (rc)
     return rc;
   /* Note that we ignore the error code on purpose. */
-  bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno);
+  bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
+           seqno, 5000);
 
   handle->t1_ns = 0;
   handle->t1_nr = 0;
@@ -1414,7 +1449,7 @@ ccid_get_atr (ccid_driver_t handle,
 
 
       rc = bulk_in (handle, msg, sizeof msg, &msglen,
-                    RDR_to_PC_DataBlock, seqno);
+                    RDR_to_PC_DataBlock, seqno, 5000);
       if (rc)
         return rc;
       
@@ -1510,7 +1545,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
 
   msg = recv_buffer;
   rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                RDR_to_PC_DataBlock, seqno);
+                RDR_to_PC_DataBlock, seqno, 5000);
   if (rc)
     return rc;
       
@@ -1683,7 +1718,7 @@ ccid_transceive (ccid_driver_t handle,
 
       msg = recv_buffer;
       rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                    RDR_to_PC_DataBlock, seqno);
+                    RDR_to_PC_DataBlock, seqno, 5000);
       if (rc)
         return rc;
       
@@ -1692,7 +1727,7 @@ ccid_transceive (ccid_driver_t handle,
       
       if (tpdulen < 4) 
         {
-          usb_clear_halt (handle->idev, 0x82);
+          usb_clear_halt (handle->idev, handle->ep_bulk_in);
           return CCID_DRIVER_ERR_ABORTED; 
         }
 #ifdef DEBUG_T1
@@ -1960,7 +1995,7 @@ ccid_transceive_secure (ccid_driver_t handle,
   
   msg = recv_buffer;
   rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen,
-                RDR_to_PC_DataBlock, seqno);
+                RDR_to_PC_DataBlock, seqno, 5000);
   if (rc)
     return rc;
   
index 63e3e28..ea296b6 100644 (file)
@@ -108,7 +108,7 @@ do_reset (ctrl_t ctrl, int do_close)
 
 \f
 static void
-reset_notify (ASSUAN_CONTEXT ctx)
+reset_notify (assuan_context_t ctx)
 {
   CTRL ctrl = assuan_get_pointer (ctx); 
 
@@ -117,7 +117,7 @@ reset_notify (ASSUAN_CONTEXT ctx)
 
 
 static int
-option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
+option_handler (assuan_context_t ctx, const char *key, const char *value)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
 
@@ -248,6 +248,10 @@ cmd_serialno (assuan_context_t ctx, char *line)
   time_t stamp;
 
   /* Clear the remove flag so that the open_card is able to reread it.  */
+
+  /* FIXME: We can't do that if we are in a locked state.  Retrun an
+     appropriate erro r in that case.  IF the card has not been
+     removed we may very well continue.  */
   if (ctrl->server_local->card_removed)
     do_reset (ctrl, 0);
 
@@ -333,9 +337,10 @@ cmd_serialno (assuan_context_t ctx, char *line)
 
    The URL to be used for locating the entire public key.
      
+   Note, that this function may be even be used on a locked card.
 */
 static int
-cmd_learn (ASSUAN_CONTEXT ctx, char *line)
+cmd_learn (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc = 0;
@@ -481,9 +486,10 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
 \f
 /* READCERT <hexified_certid>
 
+   Note, that this function may be even be used on a locked card.
  */
 static int
-cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
+cmd_readcert (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -524,7 +530,10 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
 /* READKEY <hexified_certid>
 
    Return the public key for the given cert or key ID as an standard
-   S-Expression.  */
+   S-Expression.
+
+   Note, that this function may be even be used on a locked card.
+  */
 static int
 cmd_readkey (assuan_context_t ctx, char *line)
 {
@@ -619,14 +628,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
    The client should use this command to tell us the data he want to
    sign.  */
 static int
-cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
+cmd_setdata (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int n;
   char *p;
   unsigned char *buf;
 
-  /* parse the hexstring */
+  /* FIXME: If we are locked return an error.  */
+
+  /* Parse the hexstring. */
   for (p=line,n=0; hexdigitp (p); p++, n++)
     ;
   if (*p)
@@ -652,7 +663,7 @@ cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
 static int 
 pin_cb (void *opaque, const char *info, char **retstr)
 {
-  ASSUAN_CONTEXT ctx = opaque;
+  assuan_context_t ctx = opaque;
   char *command;
   int rc;
   unsigned char *value;
@@ -687,7 +698,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
 
  */
 static int
-cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
+cmd_pksign (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -695,6 +706,8 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
   size_t outdatalen;
   char *keyidstr;
 
+  /* FIXME: If we are locked return an error.  */
+
   if ((rc = open_card (ctrl, NULL)))
     return rc;
 
@@ -738,7 +751,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
 
  */
 static int
-cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
+cmd_pkauth (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -746,6 +759,8 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
   size_t outdatalen;
   char *keyidstr;
 
+  /* FIXME: If we are locked return an error.  */
+
   if ((rc = open_card (ctrl, NULL)))
     return rc;
 
@@ -785,7 +800,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line)
 
  */
 static int
-cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
+cmd_pkdecrypt (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -793,6 +808,8 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
   size_t outdatalen;
   char *keyidstr;
 
+  /* FIXME: If we are locked return an error.  */
+
   if ((rc = open_card (ctrl, NULL)))
     return rc;
 
@@ -834,14 +851,15 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
    This command is used to retrieve data from a smartcard.  The
    allowed names depend on the currently selected smartcard
    application.  NAME must be percent and '+' escaped.  The value is
-   returned through status message, see the LESRN command for details.
+   returned through status message, see the LEARN command for details.
 
    However, the current implementation assumes that Name is not escaped;
    this works as long as noone uses arbitrary escaping. 
  
+   Note, that this function may even be used on a locked card.
 */
 static int
-cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
+cmd_getattr (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -858,6 +876,8 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
 
   /* (We ignore any garbage for now.) */
 
+  /* FIXME: Applications should not return sensistive data if the card
+     is locked.  */
   rc = app_getattr (ctrl->app_ctx, ctrl, keyword);
 
   TEST_CARD_REMOVAL (ctrl, rc);
@@ -878,7 +898,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line)
    setattr function of the actually used application (app-*.c) for
    details.  */
 static int
-cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
+cmd_setattr (assuan_context_t ctx, char *orig_line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -887,6 +907,8 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
   size_t nbytes;
   char *line, *linebuf;
 
+  /* FIXME: If we are locked return an error.  */
+
   if ((rc = open_card (ctrl, NULL)))
     return rc;
 
@@ -932,13 +954,15 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line)
 
  */
 static int
-cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
+cmd_genkey (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
   char *keyno;
   int force = has_option (line, "--force");
 
+  /* FIXME: If we are locked return an error.  */
+
   /* Skip over options. */
   while ( *line == '-' && line[1] == '-' )
     {
@@ -974,9 +998,11 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
 /* RANDOM <nbytes>
 
    Get NBYTES of random from the card and send them back as data. 
+
+   Note, that this function may be even be used on a locked card.
 */
 static int
-cmd_random (ASSUAN_CONTEXT ctx, char *line)
+cmd_random (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
@@ -1016,13 +1042,15 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line)
    Change the PIN or reset thye retry counter of the card holder
    verfication vector CHVNO. */
 static int
-cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
+cmd_passwd (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
   char *chvnostr;
   int reset_mode = has_option (line, "--reset");
 
+  /* FIXME: If we are locked return an error.  */
+
   /* Skip over options. */
   while (*line == '-' && line[1] == '-')
     {
@@ -1061,12 +1089,14 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
 
  */
 static int
-cmd_checkpin (ASSUAN_CONTEXT ctx, char *line)
+cmd_checkpin (assuan_context_t ctx, char *line)
 {
   CTRL ctrl = assuan_get_pointer (ctx);
   int rc;
   char *keyidstr;
 
+  /* FIXME: If we are locked return an error.  */
+
   if ((rc = open_card (ctrl, NULL)))
     return rc;