1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-08 12:44:23 +01:00

* 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.
This commit is contained in:
Werner Koch 2004-10-20 09:39:56 +00:00
parent 3f769cb717
commit 27d06166d3
8 changed files with 505 additions and 59 deletions

View File

@ -1,3 +1,17 @@
2004-10-20 Werner Koch <wk@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@g10code.com>
* ccid-driver.c (ccid_get_atr): Reset T=1 state info.
2004-10-17 Werner Koch <wk@g10code.com>
* passphrase.c (agent_get_passphrase): Cast UIDLEN to int. Noted

View File

@ -125,6 +125,8 @@ struct reader_table_s {
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 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn);
#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_release_context) (unsigned long context);
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 @@ long (* DLSTDCALL pcsc_set_timeout) (unsigned long context,
/*
Helper
@ -254,11 +298,13 @@ new_reader_slot (void)
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 @@ dump_pcsc_reader_status (int slot)
}
static int
reset_pcsc_reader (int slot)
{
#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
pcsc_get_status (int slot, unsigned int *status)
{
*status = 1|2|4; /* FIXME!!!! */
return 0;
}
#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];
static int
reset_pcsc_reader (int slot)
{
return SW_HOST_NOT_SUPPORTED;
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 @@ close_pcsc_reader (int slot)
#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 @@ open_pcsc_reader (const char *portstr)
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 @@ open_pcsc_reader (const char *portstr)
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 @@ open_pcsc_reader (const char *portstr)
p += strlen (p) + 1;
}
err = pcsc_connect (reader_table[slot].pcsc.context,
portstr? portstr : list,
PCSC_SHARE_EXCLUSIVE,
PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1,
&reader_table[slot].pcsc.card,
&reader_table[slot].pcsc.protocol);
if (err)
reader_table[slot].rdrname = xtrymalloc (strlen (portstr? portstr : list)+1);
if (!reader_table[slot].rdrname)
{
log_error ("pcsc_connect failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
pcsc_release_context (reader_table[slot].pcsc.context);
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)
{
log_error ("pcsc_status failed: %s (0x%lx)\n",
pcsc_error_string (err), err);
log_error ("error allocating memory for reader name\n");
pcsc_release_context (reader_table[slot].pcsc.context);
reader_table[slot].used = 0;
return -1;
}
if (atrlen >= DIM (reader_table[0].atr))
log_bug ("ATR returned by pcsc_status is too large\n");
reader_table[slot].atrlen = atrlen;
strcpy (reader_table[slot].rdrname, portstr? portstr : list);
xfree (list);
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 == 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;
}
reader_table[slot].atrlen = 0;
reader_table[slot].last_status = 0;
if (!err)
{
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);
}
}
reader_table[slot].close_reader = close_pcsc_reader;
reader_table[slot].reset_reader = reset_pcsc_reader;
@ -1311,6 +1673,12 @@ open_ccid_reader (const char *portstr)
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;
@ -1970,11 +2338,21 @@ apdu_open_reader (const char *portstr)
#ifdef _WIN32
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");
@ -1990,7 +2368,9 @@ apdu_open_reader (const char *portstr)
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 @@ apdu_open_reader (const char *portstr)
/* 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 @@ apdu_reset (int slot)
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 @@ apdu_activate (int slot)
/* 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 @@ apdu_get_status (int slot, int hang,
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;

View File

@ -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$
*/
#ifndef APDU_H

View File

@ -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$
*/
#ifndef GNUPG_SCD_APP_COMMON_H
@ -95,6 +97,7 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);
/*-- 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 @@ int app_openpgp_cardinfo (app_t app,
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_storekey (app_t app, int keyno,
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*/

View File

@ -1307,6 +1307,8 @@ ccid_get_atr (ccid_driver_t handle,
/* 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)

View File

@ -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$
*/
#ifndef CCID_DRIVER_H

View File

@ -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$
*/
#include <config.h>
@ -103,6 +105,17 @@ map_sw (int sw)
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 @@ map_sw (int sw)
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);
}

View File

@ -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$
*/
#ifndef ISO7816_H