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:
parent
3f769cb717
commit
27d06166d3
@ -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
|
||||
|
508
g10/apdu.c
508
g10/apdu.c
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user