Added command APDU
authorWerner Koch <wk@gnupg.org>
Tue, 11 Apr 2006 13:53:21 +0000 (13:53 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 11 Apr 2006 13:53:21 +0000 (13:53 +0000)
doc/scdaemon.texi
scd/ChangeLog
scd/apdu.c
scd/app-openpgp.c
scd/command.c
scd/scdaemon.c

index 24a2235..8470016 100644 (file)
@@ -347,6 +347,8 @@ syncronizing access to a token between sessions.
 * Scdaemon RANDOM::       Return random bytes generate on-card.
 * Scdaemon PASSWD::       Change PINs.
 * Scdaemon CHECKPIN::     Perform a VERIFY operation.
+* Scdaemon RESTART::      Restart connection
+* Scdaemon APDU::         Send a verbatim APDU to the card
 @end menu
 
 @node Scdaemon SERIALNO 
@@ -553,3 +555,47 @@ and only if the retry counter is still at 3.
 @end table
 
 
+
+@node Scdaemon RESTART
+@subsection Perform a RESTART operation.
+
+@example
+  RESTART
+@end example
+
+Restart the current connection; this is a kind of warm reset.  It
+deletes the context used by this connection but does not actually
+reset the card. 
+
+This is used by gpg-agent to reuse a primary pipe connection and
+may be used by clients to backup from a conflict in the serial
+command; i.e. to select another application. 
+
+
+
+
+@node Scdaemon APDU
+@subsection Send a verbatim APDU to the card.
+
+@example
+  APDU [--atr] [--more] [@var{hexstring}]
+@end example
+
+
+Send an APDU to the current reader.  This command bypasses the high
+level functions and sends the data directly to the card.
+@var{hexstring} is expected to be a proper APDU.  If @var{hexstring} is
+not given no commands are send to the card; However the command will
+implictly check whether the card is ready for use.
+
+Using the option @code{--atr} returns the ATR of the card as a status
+message before any data like this:
+@example
+     S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
+@end example
+
+Using the option @code{--more} handles the card status word MORE_DATA
+(61xx) and concatenate all reponses to one block.
+
+
+
index 27c362d..53ef676 100644 (file)
@@ -1,3 +1,12 @@
+2006-04-11  Werner Koch  <wk@g10code.com>
+
+       * command.c (hex_to_buffer): New.
+       (cmd_apdu): New.
+
+2006-04-03  Werner Koch  <wk@g10code.com>
+
+       * scdaemon.c [__GLIBC__]: Default to libpcsclite.so.1.
+
 2006-03-21  Werner Koch  <wk@g10code.com>
 
        * command.c (cmd_pksign): Add --hash option.
index adaaec6..d6bbdef 100644 (file)
@@ -2848,8 +2848,8 @@ apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1,
    HANDLE_MORE set to true this function will handle the MORE DATA
    status and return all APDUs concatenated with one status word at
    the end.  The function does not return a regular status word but 0
-   on success.  If the slot is locked, the fucntion returns
-   immediately.*/
+   on success.  If the slot is locked, the function returns
+   immediately with an error.  */
 int
 apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen,
                   int handle_more,
index fff709a..5e9281a 100644 (file)
@@ -112,8 +112,8 @@ struct app_local_s {
                            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
+    size_t keylen;      /* The length of the above S-expression.  This
+                           is usullay only required for cross checks
                            because the length of an S-expression is
                            implicitly available.  */
   } pk[3];
index 70a4269..2ed6855 100644 (file)
@@ -156,6 +156,38 @@ has_option (const char *line, const char *name)
 }
 
 
+/* Convert the STRING into a newly allocated buffer while translating
+   the hex numbers.  Stops at the first invalid character.  Blanks and
+   colons are allowed to separate the hex digits.  Returns NULL on
+   error or a newly malloced buffer and its length in LENGTH.  */
+static unsigned char *
+hex_to_buffer (const char *string, size_t *r_length)
+{
+  unsigned char *buffer;
+  const char *s;
+  size_t n;
+
+  buffer = xtrymalloc (strlen (string)+1);
+  if (!buffer)
+    return NULL;
+  for (s=string, n=0; *s; s++)
+    {
+      if (spacep (s) || *s == ':') 
+        continue;
+      if (hexdigitp (s) && hexdigitp (s+1))
+        {
+          buffer[n++] = xtoi_2 (s);
+          s++;
+        }
+      else
+        break;
+    }
+  *r_length = n;
+  return buffer;
+}
+
+
+
 /* Reset the card and free the application context.  With SEND_RESET
    set to true actually send a RESET to the reader. */
 static void
@@ -1372,6 +1404,101 @@ cmd_restart (assuan_context_t ctx, char *line)
 }
 
 
+/* APDU [--atr] [--more] [hexstring]
+
+   Send an APDU to the current reader.  This command bypasses the high
+   level functions and sends the data directly to the card.  HEXSTRING
+   is expected to be a proper APDU.  If HEXSTRING is not given no
+   commands are set to the card but the command will implictly check
+   whether the card is ready for use. 
+
+   Using the option "--atr" returns the ATR of the card as a status
+   message before any data like this:
+     S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1
+
+   Using the option --more handles the card status word MORE_DATA
+   (61xx) and concatenate all reponses to one block.
+
+ */
+static int
+cmd_apdu (assuan_context_t ctx, char *line)
+{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  int rc;
+  int rc_is_assuan = 0;
+  unsigned char *apdu;
+  size_t apdulen;
+  int with_atr;
+  int handle_more;
+
+  with_atr = has_option (line, "--atr");
+  handle_more = has_option (line, "--more");
+
+  /* Skip over options. */
+  while ( *line == '-' && line[1] == '-' )
+    {
+      while (*line && !spacep (line))
+        line++;
+      while (spacep (line))
+        line++;
+    }
+
+  if ( IS_LOCKED (ctrl) )
+    return gpg_error (GPG_ERR_LOCKED);
+
+  if ((rc = open_card (ctrl, NULL)))
+    return rc;
+
+  if (with_atr)
+    {
+      unsigned char *atr;
+      size_t atrlen;
+      int i;
+      char hexbuf[400];
+      
+      atr = apdu_get_atr (ctrl->reader_slot, &atrlen);
+      if (!atr || atrlen > sizeof hexbuf - 2 )
+        {
+          rc = gpg_error (GPG_ERR_INV_CARD);
+          goto leave;
+        }
+      for (i=0; i < atrlen; i++)
+        sprintf (hexbuf+2*i, "%02X", atr[i]);
+      xfree (atr);
+      send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
+    }
+
+  apdu = hex_to_buffer (line, &apdulen);
+  if (!apdu)
+    {
+      rc = gpg_error_from_errno (errno);
+      goto leave;
+    }
+  if (apdulen)
+    {
+      unsigned char *result = NULL;
+      size_t resultlen;
+
+      rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more,
+                             &result, &resultlen);
+      if (rc)
+        log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc));
+      else
+        {
+          rc_is_assuan = 1;
+          rc = assuan_send_data (ctx, result, resultlen);
+          xfree (result);
+        }
+    }
+  xfree (apdu);
+
+ leave:
+  TEST_CARD_REMOVAL (ctrl, rc);
+  return rc_is_assuan? rc : map_to_assuan_status (rc);
+}
+
+
+
 
 \f
 /* Tell the assuan library about our commands */
@@ -1403,6 +1530,7 @@ register_commands (assuan_context_t ctx)
     { "UNLOCK",       cmd_unlock },
     { "GETINFO",      cmd_getinfo },
     { "RESTART",      cmd_restart },
+    { "APDU",         cmd_apdu },
     { NULL }
   };
   int i, rc;
index 56c0d76..e24b421 100644 (file)
@@ -139,6 +139,8 @@ static ARGPARSE_OPTS opts[] = {
 /* The card dirver we use by default for PC/SC.  */
 #if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
 #define DEFAULT_PCSC_DRIVER "winscard.dll"
+#elif defined(__GLIBC__)
+#define DEFAULT_PCSC_DRIVER "libpcsclite.so.1"
 #else
 #define DEFAULT_PCSC_DRIVER "libpcsclite.so"
 #endif