gnupg/g10 (9 files)
cvs user wk
cvs at cvs.gnupg.org
Wed Oct 20 11:36:42 CEST 2004
Date: Wednesday, October 20, 2004 @ 11:39:56
Author: wk
Path: /cvs/gnupg/gnupg/g10
Modified: ChangeLog apdu.c apdu.h app-common.h app-openpgp.c ccid-driver.c
ccid-driver.h iso7816.c iso7816.h
* apdu.c (apdu_open_reader): Load pcsc_get_status_change fucntion.
(pcsc_get_status): Implemented.
(reset_pcsc_reader): Implemented.
(open_pcsc_reader): Succeed even with no card inserted.
(open_ccid_reader): Set LAST_STATUS.
* iso7816.c (iso7816_select_application): Always use 0 for P1.
---------------+
ChangeLog | 14 +
apdu.c | 486 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
apdu.h | 2
app-common.h | 12 -
app-openpgp.c | 2
ccid-driver.c | 4
ccid-driver.h | 2
iso7816.c | 22 +-
iso7816.h | 2
9 files changed, 496 insertions(+), 50 deletions(-)
Index: gnupg/g10/ChangeLog
diff -u gnupg/g10/ChangeLog:1.623 gnupg/g10/ChangeLog:1.624
--- gnupg/g10/ChangeLog:1.623 Sun Oct 17 15:28:37 2004
+++ gnupg/g10/ChangeLog Wed Oct 20 11:39:56 2004
@@ -1,3 +1,17 @@
+2004-10-20 Werner Koch <wk at g10code.com>
+
+ * apdu.c (apdu_open_reader): Load pcsc_get_status_change fucntion.
+ (pcsc_get_status): Implemented.
+ (reset_pcsc_reader): Implemented.
+ (open_pcsc_reader): Succeed even with no card inserted.
+ (open_ccid_reader): Set LAST_STATUS.
+
+ * iso7816.c (iso7816_select_application): Always use 0 for P1.
+
+2004-10-18 Werner Koch <wk at g10code.com>
+
+ * ccid-driver.c (ccid_get_atr): Reset T=1 state info.
+
2004-10-17 Werner Koch <wk at g10code.com>
* passphrase.c (agent_get_passphrase): Cast UIDLEN to int. Noted
Index: gnupg/g10/apdu.c
diff -u gnupg/g10/apdu.c:1.15 gnupg/g10/apdu.c:1.16
--- gnupg/g10/apdu.c:1.15 Fri Oct 15 15:16:57 2004
+++ gnupg/g10/apdu.c Wed Oct 20 11:39:56 2004
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: apdu.c,v 1.15 2004/10/15 13:16:57 werner Exp $
+ * $Id: apdu.c,v 1.16 2004/10/20 09:39:56 wk Exp $
*/
#include <config.h>
@@ -125,6 +125,8 @@
rapdu_t handle;
} rapdu;
#endif /*USE_G10CODE_RAPDU*/
+ char *rdrname; /* Name of the connected reader or NULL if unknown. */
+ int last_status;
int status;
unsigned char atr[33];
size_t atrlen; /* A zero length indicates that the ATR has
@@ -169,13 +171,47 @@
#define PCSC_UNPOWER_CARD 2
#define PCSC_EJECT_CARD 3
-struct pcsc_io_request_s {
+#define PCSC_UNKNOWN 0x0001
+#define PCSC_ABSENT 0x0002 /* Card is absent. */
+#define PCSC_PRESENT 0x0004 /* Card is present. */
+#define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */
+#define PCSC_POWERED 0x0010 /* Card is powered. */
+#define PCSC_NEGOTIABLE 0x0020 /* Card is awaiting PTS. */
+#define PCSC_SPECIFIC 0x0040 /* Card is ready for use. */
+
+#define PCSC_STATE_UNAWARE 0x0000 /* Want status. */
+#define PCSC_STATE_IGNORE 0x0001 /* Ignore this reader. */
+#define PCSC_STATE_CHANGED 0x0002 /* State has changed. */
+#define PCSC_STATE_UNKNOWN 0x0004 /* Reader unknown. */
+#define PCSC_STATE_UNAVAILABLE 0x0008 /* Status unavailable. */
+#define PCSC_STATE_EMPTY 0x0010 /* Card removed. */
+#define PCSC_STATE_PRESENT 0x0020 /* Card inserted. */
+#define PCSC_STATE_ATRMATCH 0x0040 /* ATR matches card. */
+#define PCSC_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode. */
+#define PCSC_STATE_INUSE 0x0100 /* Shared mode. */
+#define PCSC_STATE_MUTE 0x0200 /* Unresponsive card. */
+
+
+struct pcsc_io_request_s
+{
unsigned long protocol;
unsigned long pci_len;
};
typedef struct pcsc_io_request_s *pcsc_io_request_t;
+struct pcsc_readerstate_s
+{
+ const char *reader;
+ void *user_data;
+ unsigned long current_state;
+ unsigned long event_state;
+ unsigned long atrlen;
+ unsigned char atr[33];
+};
+
+typedef struct pcsc_readerstate_s *pcsc_readerstate_t;
+
long (* DLSTDCALL pcsc_establish_context) (unsigned long scope,
const void *reserved1,
const void *reserved2,
@@ -184,12 +220,21 @@
long (* DLSTDCALL pcsc_list_readers) (unsigned long context,
const char *groups,
char *readers, unsigned long*readerslen);
+long (* DLSTDCALL pcsc_get_status_change) (unsigned long context,
+ unsigned long timeout,
+ pcsc_readerstate_t readerstates,
+ unsigned long nreaderstates);
long (* DLSTDCALL pcsc_connect) (unsigned long context,
const char *reader,
unsigned long share_mode,
unsigned long preferred_protocols,
unsigned long *r_card,
unsigned long *r_active_protocol);
+long (* DLSTDCALL pcsc_reconnect) (unsigned long card,
+ unsigned long share_mode,
+ unsigned long preferred_protocols,
+ unsigned long initialization,
+ unsigned long *r_active_protocol);
long (* DLSTDCALL pcsc_disconnect) (unsigned long card,
unsigned long disposition);
long (* DLSTDCALL pcsc_status) (unsigned long card,
@@ -211,7 +256,6 @@
-
/*
Helper
@@ -254,11 +298,13 @@
reader_table[reader].dump_status_reader = NULL;
reader_table[reader].used = 1;
+ reader_table[reader].last_status = 0;
#ifdef NEED_PCSC_WRAPPER
reader_table[reader].pcsc.req_fd = -1;
reader_table[reader].pcsc.rsp_fd = -1;
reader_table[reader].pcsc.pid = (pid_t)(-1);
#endif
+
return reader;
}
@@ -662,18 +708,293 @@
}
-
static int
-pcsc_get_status (int slot, unsigned int *status)
+reset_pcsc_reader (int slot)
{
- *status = 1|2|4; /* FIXME!!!! */
+#ifdef NEED_PCSC_WRAPPER
+ long err;
+ reader_table_t slotp;
+ size_t len;
+ int i, n;
+ unsigned char msgbuf[9];
+
+ slotp = reader_table + slot;
+
+ if (slotp->pcsc.req_fd == -1
+ || slotp->pcsc.rsp_fd == -1
+ || slotp->pcsc.pid == (pid_t)(-1) )
+ {
+ log_error ("pcsc_get_status: pcsc-wrapper not running\n");
+ return SW_HOST_CARD_IO_ERROR;
+ }
+
+ msgbuf[0] = 0x05; /* RESET command. */
+ len = 0;
+ msgbuf[1] = (len >> 24);
+ msgbuf[2] = (len >> 16);
+ msgbuf[3] = (len >> 8);
+ msgbuf[4] = (len );
+ if ( writen (slotp->pcsc.req_fd, msgbuf, 5) )
+ {
+ log_error ("error sending PC/SC RESET request: %s\n",
+ strerror (errno));
+ goto command_failed;
+ }
+
+ /* Read the response. */
+ if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
+ {
+ log_error ("error receiving PC/SC RESET response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+ len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+ if (msgbuf[0] != 0x81 || len < 4)
+ {
+ log_error ("invalid response header from PC/SC received\n");
+ goto command_failed;
+ }
+ len -= 4; /* Already read the error code. */
+ if (len > DIM (slotp->atr))
+ {
+ log_error ("PC/SC returned a too large ATR (len=%x)\n", len);
+ goto command_failed;
+ }
+ err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8];
+ if (err)
+ {
+ log_error ("PC/SC RESET failed: %s\n", pcsc_error_string (err));
+ goto command_failed;
+ }
+
+ /* The open fucntion may return a zero for the ATR length to
+ indicate that no card is present. */
+ n = len;
+ if (n)
+ {
+ if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n)
+ {
+ log_error ("error receiving PC/SC RESET response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+ }
+ slotp->atrlen = len;
+
+ return 0;
+
+ command_failed:
+ close (slotp->pcsc.req_fd);
+ close (slotp->pcsc.rsp_fd);
+ slotp->pcsc.req_fd = -1;
+ slotp->pcsc.rsp_fd = -1;
+ kill (slotp->pcsc.pid, SIGTERM);
+ slotp->pcsc.pid = (pid_t)(-1);
+ slotp->used = 0;
+ return -1;
+
+#else /* !NEED_PCSC_WRAPPER */
+ long err;
+ char reader[250];
+ unsigned long nreader, atrlen;
+ unsigned long card_state, card_protocol;
+
+ if (reader_table[slot].pcsc.card)
+ {
+ err = pcsc_disconnect (reader_table[slot].pcsc.card, PCSC_LEAVE_CARD);
+ if (err)
+ {
+ log_error ("pcsc_disconnect failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ return SW_HOST_CARD_IO_ERROR;
+ }
+ reader_table[slot].pcsc.card = 0;
+ }
+
+ err = pcsc_connect (reader_table[slot].pcsc.context,
+ reader_table[slot].rdrname,
+ PCSC_SHARE_EXCLUSIVE,
+ PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
+ &reader_table[slot].pcsc.card,
+ &reader_table[slot].pcsc.protocol);
+ if (err)
+ {
+ log_error ("pcsc_connect failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ reader_table[slot].pcsc.card = 0;
+ return SW_HOST_CARD_IO_ERROR;
+ }
+
+
+ atrlen = 33;
+ nreader = sizeof reader - 1;
+ err = pcsc_status (reader_table[slot].pcsc.card,
+ reader, &nreader,
+ &card_state, &card_protocol,
+ reader_table[slot].atr, &atrlen);
+ if (err)
+ {
+ log_error ("pcsc_status failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ reader_table[slot].atrlen = 0;
+ return SW_HOST_CARD_IO_ERROR;
+ }
+ if (atrlen >= DIM (reader_table[0].atr))
+ log_bug ("ATR returned by pcsc_status is too large\n");
+ reader_table[slot].atrlen = atrlen;
+
return 0;
+#endif /* !NEED_PCSC_WRAPPER */
}
+
static int
-reset_pcsc_reader (int slot)
+pcsc_get_status (int slot, unsigned int *status)
{
- return SW_HOST_NOT_SUPPORTED;
+#ifdef NEED_PCSC_WRAPPER
+ long err;
+ reader_table_t slotp;
+ size_t len, full_len;
+ int i, n;
+ unsigned char msgbuf[9];
+ unsigned char buffer[12];
+
+ slotp = reader_table + slot;
+
+ if (slotp->pcsc.req_fd == -1
+ || slotp->pcsc.rsp_fd == -1
+ || slotp->pcsc.pid == (pid_t)(-1) )
+ {
+ log_error ("pcsc_get_status: pcsc-wrapper not running\n");
+ return SW_HOST_CARD_IO_ERROR;
+ }
+
+ msgbuf[0] = 0x04; /* STATUS command. */
+ len = 0;
+ msgbuf[1] = (len >> 24);
+ msgbuf[2] = (len >> 16);
+ msgbuf[3] = (len >> 8);
+ msgbuf[4] = (len );
+ if ( writen (slotp->pcsc.req_fd, msgbuf, 5) )
+ {
+ log_error ("error sending PC/SC STATUS request: %s\n",
+ strerror (errno));
+ goto command_failed;
+ }
+
+ /* Read the response. */
+ if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9)
+ {
+ log_error ("error receiving PC/SC STATUS response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+ len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+ if (msgbuf[0] != 0x81 || len < 4)
+ {
+ log_error ("invalid response header from PC/SC received\n");
+ goto command_failed;
+ }
+ len -= 4; /* Already read the error code. */
+ err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8];
+ if (err)
+ {
+ log_error ("pcsc_status failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ return SW_HOST_CARD_IO_ERROR;
+ }
+
+ full_len = len;
+
+ n = 8 < len ? 8 : len;
+ if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != 8)
+ {
+ log_error ("error receiving PC/SC STATUS response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+
+ full_len -= len;
+ /* Newer versions of the wrapper might send more status bytes.
+ Read them. */
+ while (full_len)
+ {
+ unsigned char dummybuf[128];
+
+ n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf);
+ if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n)
+ {
+ log_error ("error receiving PC/SC TRANSMIT response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+ full_len -= n;
+ }
+
+ /* We are lucky: The wrapper already returns the data in the
+ required format. */
+ *status = buffer[3];
+
+ return 0;
+
+ command_failed:
+ close (slotp->pcsc.req_fd);
+ close (slotp->pcsc.rsp_fd);
+ slotp->pcsc.req_fd = -1;
+ slotp->pcsc.rsp_fd = -1;
+ kill (slotp->pcsc.pid, SIGTERM);
+ slotp->pcsc.pid = (pid_t)(-1);
+ slotp->used = 0;
+ return -1;
+
+#else /*!NEED_PCSC_WRAPPER*/
+
+ long err;
+ struct pcsc_readerstate_s rdrstates[1];
+
+ memset (rdrstates, 0, sizeof *rdrstates);
+ rdrstates[0].reader = reader_table[slot].rdrname;
+ rdrstates[0].current_state = PCSC_STATE_UNAWARE;
+ err = pcsc_get_status_change (reader_table[slot].pcsc.context,
+ 0,
+ rdrstates, 1);
+ if (err == 0x8010000a) /* Timeout. */
+ err = 0;
+ if (err)
+ {
+ log_error ("pcsc_get_status_change failed: %s (0x%lx)\n",
+ pcsc_error_string (err), err);
+ return SW_HOST_CARD_IO_ERROR;
+ }
+
+
+ /* log_debug */
+ /* ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", */
+ /* (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_INUSE)? " unuse":"", */
+ /* (rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" ); */
+
+ *status = 0;
+ if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) )
+ *status |= 2;
+ if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) )
+ *status |= 4;
+ /* We indicate a useful card if it is not in use by another
+ application. This is because we only use exclusive access
+ mode. */
+ if ( (*status & 6) == 6
+ && !(rdrstates[0].event_state & PCSC_STATE_INUSE) )
+ *status |= 1;
+
+ return 0;
+#endif /*!NEED_PCSC_WRAPPER*/
}
@@ -889,6 +1210,8 @@
#else /*!NEED_PCSC_WRAPPER*/
pcsc_release_context (reader_table[slot].pcsc.context);
+ xfree (reader_table[slot].rdrname);
+ reader_table[slot].rdrname = NULL;
reader_table[slot].used = 0;
return 0;
#endif /*!NEED_PCSC_WRAPPER*/
@@ -999,8 +1322,14 @@
slotp->pcsc.rsp_fd = rp[0];
/* Wait for the intermediate child to terminate. */
- while ( (i=pth_waitpid (pid, NULL, 0)) == -1 && errno == EINTR)
+#ifdef USE_GNU_PTH
+#define WAIT pth_waitpid
+#else
+#define WAIT waitpid
+#endif
+ while ( (i=WAIT (pid, NULL, 0)) == -1 && errno == EINTR)
;
+#undef X
/* Now send the open request. */
msgbuf[0] = 0x01; /* OPEN command. */
@@ -1041,12 +1370,23 @@
log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err));
goto command_failed;
}
+
+ slotp->last_status = 0;
+
+ /* The open fucntion may return a zero for the ATR length to
+ indicate that no card is present. */
n = len;
- if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n)
+ if (n)
{
- log_error ("error receiving PC/SC OPEN response: %s\n",
- i? strerror (errno) : "premature EOF");
- goto command_failed;
+ if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n)
+ {
+ log_error ("error receiving PC/SC OPEN response: %s\n",
+ i? strerror (errno) : "premature EOF");
+ goto command_failed;
+ }
+ /* If we got to here we know that a card is present
+ and usable. Thus remember this. */
+ slotp->last_status = (1|2|4| 0x8000);
}
slotp->atrlen = len;
@@ -1132,41 +1472,63 @@
p += strlen (p) + 1;
}
+ reader_table[slot].rdrname = xtrymalloc (strlen (portstr? portstr : list)+1);
+ if (!reader_table[slot].rdrname)
+ {
+ log_error ("error allocating memory for reader name\n");
+ pcsc_release_context (reader_table[slot].pcsc.context);
+ reader_table[slot].used = 0;
+ return -1;
+ }
+ strcpy (reader_table[slot].rdrname, portstr? portstr : list);
+ xfree (list);
+
err = pcsc_connect (reader_table[slot].pcsc.context,
- portstr? portstr : list,
+ reader_table[slot].rdrname,
PCSC_SHARE_EXCLUSIVE,
PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
&reader_table[slot].pcsc.card,
&reader_table[slot].pcsc.protocol);
- if (err)
+ if (err == 0x8010000c) /* No smartcard. */
+ reader_table[slot].pcsc.card = 0;
+ else if (err)
{
log_error ("pcsc_connect failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
pcsc_release_context (reader_table[slot].pcsc.context);
+ xfree (reader_table[slot].rdrname);
+ reader_table[slot].rdrname = NULL;
reader_table[slot].used = 0;
xfree (list);
return -1;
}
-
- atrlen = 32;
- /* (We need to pass a dummy buffer. We use LIST because it ought to
- be large enough.) */
- err = pcsc_status (reader_table[slot].pcsc.card,
- list, &listlen,
- &card_state, &card_protocol,
- reader_table[slot].atr, &atrlen);
- xfree (list);
- if (err)
+
+ reader_table[slot].atrlen = 0;
+ reader_table[slot].last_status = 0;
+ if (!err)
{
- log_error ("pcsc_status failed: %s (0x%lx)\n",
- pcsc_error_string (err), err);
- pcsc_release_context (reader_table[slot].pcsc.context);
- reader_table[slot].used = 0;
- return -1;
+ char reader[250];
+ unsigned long readerlen;
+
+ atrlen = 32;
+ readerlen = sizeof reader -1 ;
+ err = pcsc_status (reader_table[slot].pcsc.card,
+ reader, &readerlen,
+ &card_state, &card_protocol,
+ reader_table[slot].atr, &atrlen);
+ if (err)
+ log_error ("pcsc_status failed: %s (0x%lx) %lu\n",
+ pcsc_error_string (err), err, readerlen);
+ else
+ {
+ if (atrlen >= DIM (reader_table[0].atr))
+ log_bug ("ATR returned by pcsc_status is too large\n");
+ reader_table[slot].atrlen = atrlen;
+ /* If we got to here we know that a card is present
+ and usable. Thus remember this. */
+ reader_table[slot].last_status = (1|2|4| 0x8000);
+ }
}
- if (atrlen >= DIM (reader_table[0].atr))
- log_bug ("ATR returned by pcsc_status is too large\n");
- reader_table[slot].atrlen = atrlen;
reader_table[slot].close_reader = close_pcsc_reader;
reader_table[slot].reset_reader = reset_pcsc_reader;
@@ -1311,6 +1673,12 @@
slotp->atrlen = 0;
err = 0;
}
+ else
+ {
+ /* If we got to here we know that a card is present
+ and usable. Thus remember this. */
+ reader_table[slot].last_status = (1|2|4| 0x8000);
+ }
reader_table[slot].close_reader = close_ccid_reader;
reader_table[slot].shutdown_reader = shutdown_ccid_reader;
@@ -1971,11 +2339,21 @@
if (!pcsc_list_readers)
pcsc_list_readers = dlsym (handle, "SCardListReadersA");
#endif
+ pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange");
+#ifdef _WIN32
+ if (!pcsc_get_status_change)
+ pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA");
+#endif
pcsc_connect = dlsym (handle, "SCardConnect");
#ifdef _WIN32
if (!pcsc_connect)
pcsc_connect = dlsym (handle, "SCardConnectA");
#endif
+ pcsc_reconnect = dlsym (handle, "SCardReconnect");
+#ifdef _WIN32
+ if (!pcsc_reconnect)
+ pcsc_reconnect = dlsym (handle, "SCardReconnectA");
+#endif
pcsc_disconnect = dlsym (handle, "SCardDisconnect");
pcsc_status = dlsym (handle, "SCardStatus");
#ifdef _WIN32
@@ -1990,7 +2368,9 @@
if (!pcsc_establish_context
|| !pcsc_release_context
|| !pcsc_list_readers
+ || !pcsc_get_status_change
|| !pcsc_connect
+ || !pcsc_reconnect
|| !pcsc_disconnect
|| !pcsc_status
|| !pcsc_begin_transaction
@@ -2001,11 +2381,13 @@
/* Note that set_timeout is currently not used and also not
available under Windows. */
log_error ("apdu_open_reader: invalid PC/SC driver "
- "(%d%d%d%d%d%d%d%d%d%d)\n",
+ "(%d%d%d%d%d%d%d%d%d%d%d%d)\n",
!!pcsc_establish_context,
!!pcsc_release_context,
!!pcsc_list_readers,
+ !!pcsc_get_status_change,
!!pcsc_connect,
+ !!pcsc_reconnect,
!!pcsc_disconnect,
!!pcsc_status,
!!pcsc_begin_transaction,
@@ -2106,9 +2488,17 @@
if ((sw = lock_slot (slot)))
return sw;
+ reader_table[slot].last_status = 0;
if (reader_table[slot].reset_reader)
sw = reader_table[slot].reset_reader (slot);
+ if (!sw)
+ {
+ /* If we got to here we know that a card is present
+ and usable. Thus remember this. */
+ reader_table[slot].last_status = (1|2|4| 0x8000);
+ }
+
unlock_slot (slot);
return sw;
}
@@ -2143,7 +2533,16 @@
/* We don't have an ATR or a card is present though inactive:
do a reset now. */
if (reader_table[slot].reset_reader)
- sw = reader_table[slot].reset_reader (slot);
+ {
+ reader_table[slot].last_status = 0;
+ sw = reader_table[slot].reset_reader (slot);
+ if (!sw)
+ {
+ /* If we got to here we know that a card is present
+ and usable. Thus remember this. */
+ reader_table[slot].last_status = (1|2|4| 0x8000);
+ }
+ }
}
}
@@ -2205,7 +2604,22 @@
unlock_slot (slot);
if (sw)
- return sw;
+ {
+ reader_table[slot].last_status = 0;
+ return sw;
+ }
+
+ /* Keep track of changes. We use one extra bit to test whether we
+ have checked the status at least once. */
+ if ( s != (reader_table[slot].last_status & 0x07ff)
+ || !reader_table[slot].last_status )
+ {
+ reader_table[slot].change_counter++;
+ /* Make sure that the ATR is invalid so that a reset will be by
+ activate. */
+ reader_table[slot].atrlen = 0;
+ }
+ reader_table[slot].last_status = (s | 0x8000);
if (status)
*status = s;
Index: gnupg/g10/apdu.h
diff -u gnupg/g10/apdu.h:1.5 gnupg/g10/apdu.h:1.6
--- gnupg/g10/apdu.h:1.5 Mon Sep 20 15:15:37 2004
+++ gnupg/g10/apdu.h Wed Oct 20 11:39:56 2004
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: apdu.h,v 1.6 2004/10/20 09:39:56 wk Exp $
*/
#ifndef APDU_H
Index: gnupg/g10/app-common.h
diff -u gnupg/g10/app-common.h:1.5 gnupg/g10/app-common.h:1.6
--- gnupg/g10/app-common.h:1.5 Thu Sep 23 15:32:31 2004
+++ gnupg/g10/app-common.h Wed Oct 20 11:39:56 2004
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: app-common.h,v 1.6 2004/10/20 09:39:56 wk Exp $
*/
#ifndef GNUPG_SCD_APP_COMMON_H
@@ -95,6 +97,7 @@
/*-- app.c --*/
app_t select_application (ctrl_t ctrl, int slot, const char *name);
void release_application (app_t app);
+int app_munge_serialno (app_t app);
int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp);
int app_write_learn_status (app_t app, ctrl_t ctrl);
int app_readcert (app_t app, const char *certid,
@@ -143,7 +146,6 @@
unsigned char **fpr1,
unsigned char **fpr2,
unsigned char **fpr3);
-#endif /* GNUPG_MAJOR_VERSION != 1 */
int app_openpgp_storekey (app_t app, int keyno,
unsigned char *template, size_t template_len,
time_t created_at,
@@ -154,16 +156,18 @@
int app_openpgp_readkey (app_t app, int keyno,
unsigned char **m, size_t *mlen,
unsigned char **e, size_t *elen);
-#if GNUPG_MAJOR_VERSION == 1
-#else
/*-- app-nks.c --*/
int app_select_nks (app_t app);
/*-- app-dinsig.c --*/
int app_select_dinsig (app_t app);
+/*-- app-p15.c --*/
+int app_select_p15 (app_t app);
+
+
+#endif
-#endif /* GNUPG_MAJOR_VERSION != 1 */
#endif /*GNUPG_SCD_APP_COMMON_H*/
Index: gnupg/g10/app-openpgp.c
diff -u gnupg/g10/app-openpgp.c:1.15 gnupg/g10/app-openpgp.c:1.16
--- gnupg/g10/app-openpgp.c:1.15 Fri Oct 15 11:55:39 2004
+++ gnupg/g10/app-openpgp.c Wed Oct 20 11:39:56 2004
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: app-openpgp.c,v 1.15 2004/10/15 09:55:39 werner Exp $
+ * $Id: app-openpgp.c,v 1.16 2004/10/20 09:39:56 wk Exp $
*/
#include <config.h>
Index: gnupg/g10/ccid-driver.c
diff -u gnupg/g10/ccid-driver.c:1.18 gnupg/g10/ccid-driver.c:1.19
--- gnupg/g10/ccid-driver.c:1.18 Fri Oct 15 15:16:57 2004
+++ gnupg/g10/ccid-driver.c Wed Oct 20 11:39:56 2004
@@ -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: ccid-driver.c,v 1.18 2004/10/15 13:16:57 werner Exp $
+ * $Id: ccid-driver.c,v 1.19 2004/10/20 09:39:56 wk Exp $
*/
@@ -1307,6 +1307,8 @@
/* Note that we ignore the error code on purpose. */
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno);
+ handle->t1_ns = 0;
+ handle->t1_nr = 0;
/* Send an S-Block with our maximun IFSD to the CCID. */
if (!handle->auto_ifsd)
Index: gnupg/g10/ccid-driver.h
diff -u gnupg/g10/ccid-driver.h:1.8 gnupg/g10/ccid-driver.h:1.9
--- gnupg/g10/ccid-driver.h:1.8 Mon Oct 11 10:44:34 2004
+++ gnupg/g10/ccid-driver.h Wed Oct 20 11:39:56 2004
@@ -50,6 +50,8 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: ccid-driver.h,v 1.9 2004/10/20 09:39:56 wk Exp $
*/
#ifndef CCID_DRIVER_H
Index: gnupg/g10/iso7816.c
diff -u gnupg/g10/iso7816.c:1.4 gnupg/g10/iso7816.c:1.5
--- gnupg/g10/iso7816.c:1.4 Thu Sep 9 20:18:34 2004
+++ gnupg/g10/iso7816.c Wed Oct 20 11:39:56 2004
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: iso7816.c,v 1.5 2004/10/20 09:39:56 wk Exp $
*/
#include <config.h>
@@ -103,6 +105,17 @@
return gpg_error (ec);
}
+/* Map a status word from the APDU layer to a gpg-error code. */
+gpg_error_t
+iso7816_map_sw (int sw)
+{
+ /* All APDU functions should return 0x9000 on success but for
+ historical reasons of the implementation some return 0 to
+ indicate success. We allow for that here. */
+ return sw? map_sw (sw) : 0;
+}
+
+
/* This function is specialized version of the SELECT FILE command.
SLOT is the card and reader as created for example by
apdu_open_reader (), AID is a buffer of size AIDLEN holding the
@@ -113,15 +126,8 @@
gpg_error_t
iso7816_select_application (int slot, const char *aid, size_t aidlen)
{
- static char const openpgp_aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 };
int sw;
- int p1 = 0x0C; /* No FCI to be returned. */
-
- if (aidlen == sizeof openpgp_aid
- && !memcmp (aid, openpgp_aid, sizeof openpgp_aid))
- p1 = 0; /* The current openpgp cards don't allow 0x0c. */
-
- sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, p1, aidlen, aid);
+ sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid);
return map_sw (sw);
}
Index: gnupg/g10/iso7816.h
diff -u gnupg/g10/iso7816.h:1.4 gnupg/g10/iso7816.h:1.5
--- gnupg/g10/iso7816.h:1.4 Mon Oct 11 10:44:34 2004
+++ gnupg/g10/iso7816.h Wed Oct 20 11:39:56 2004
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: iso7816.h,v 1.5 2004/10/20 09:39:56 wk Exp $
*/
#ifndef ISO7816_H
More information about the Gnupg-commits
mailing list