diff options
author | NIIBE Yutaka <[email protected]> | 2017-03-06 05:18:06 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2017-03-06 05:18:06 +0000 |
commit | cb6337329d3c858c695a7e56e2fc31d9d50ca3fe (patch) | |
tree | 959ff2c7ab7ec284cdf6e510c9f5b453b22a51f4 | |
parent | scd: Fix API of select_file/_path. (diff) | |
download | gnupg-cb6337329d3c858c695a7e56e2fc31d9d50ca3fe.tar.gz gnupg-cb6337329d3c858c695a7e56e2fc31d9d50ca3fe.zip |
scd: Clean up old code.
* scd/apdu.c (CT_init, CT_data, CT_close): Remove.
(ct_error_string, ct_activate_card, close_ct_reader, reset_ct_reader)
(ct_get_status, ct_send_apdu, open_ct_reader): Remove.
(new_reader_slot) [NEED_PCSC_WRAPPER]: Remove fd and pid handling.
(writen, readn): Remove.
(pcsc_get_status, pcsc_send_apdu, control_pcsc, close_pcsc_reader)
(reset_pcsc_reader, open_pcsc_reader): Only DIRECT version.
(apdu_open_one_reader): Remove CT_api handling.
(apdu_get_status_internal, send_le): Fix to stop warnings.
Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to '')
-rw-r--r-- | scd/apdu.c | 1167 |
1 files changed, 22 insertions, 1145 deletions
diff --git a/scd/apdu.c b/scd/apdu.c index 9df1572f5..c8ce68473 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -73,16 +73,6 @@ struct dev_list { int idx_max; }; -/* Due to conflicting use of threading libraries we usually can't link - against libpcsclite if we are using Pth. Instead we use a wrapper - program. Note that with nPth there is no need for a wrapper. */ -#ifdef USE_PTH /* Right, plain old Pth. */ -#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__) -#define NEED_PCSC_WRAPPER 1 -#endif -#endif - - #define MAX_READER 4 /* Number of readers we support concurrently. */ @@ -129,11 +119,6 @@ struct reader_table_s { pcsc_dword_t modify_ioctl; int pinmin; int pinmax; -#ifdef NEED_PCSC_WRAPPER - int req_fd; - int rsp_fd; - pid_t pid; -#endif /*NEED_PCSC_WRAPPER*/ } pcsc; #ifdef USE_G10CODE_RAPDU struct { @@ -165,14 +150,6 @@ static npth_mutex_t reader_table_lock; #endif -/* ct API function pointer. */ -static char (* DLSTDCALL CT_init) (unsigned short ctn, unsigned short Pn); -static char (* DLSTDCALL CT_data) (unsigned short ctn, unsigned char *dad, - unsigned char *sad, unsigned short lc, - unsigned char *cmd, unsigned short *lr, - unsigned char *rsp); -static char (* DLSTDCALL CT_close) (unsigned short ctn); - /* PC/SC constants and function pointer. */ #define PCSC_SCOPE_USER 0 #define PCSC_SCOPE_TERMINAL 1 @@ -472,11 +449,6 @@ new_reader_slot (void) reader_table[reader].is_spr532 = 0; reader_table[reader].pinpad_varlen_supported = 0; reader_table[reader].require_get_status = 1; -#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 reader_table[reader].pcsc.verify_ioctl = 0; reader_table[reader].pcsc.modify_ioctl = 0; reader_table[reader].pcsc.pinmin = -1; @@ -562,268 +534,11 @@ apdu_strerror (int rc) return "unknown status error"; } } - - - -/* - ct API Interface - */ - -static const char * -ct_error_string (long err) -{ - switch (err) - { - case 0: return "okay"; - case -1: return "invalid data"; - case -8: return "ct error"; - case -10: return "transmission error"; - case -11: return "memory allocation error"; - case -128: return "HTSI error"; - default: return "unknown CT-API error"; - } -} - - -/* Wait for the card in SLOT and activate it. Return a status word - error or 0 on success. */ -static int -ct_activate_card (int slot) -{ - int rc; - unsigned char dad[1], sad[1], cmd[11], buf[256]; - unsigned short buflen; - - /* Check whether card has been inserted. */ - dad[0] = 1; /* Destination address: CT. */ - sad[0] = 2; /* Source address: Host. */ - - cmd[0] = 0x20; /* Class byte. */ - cmd[1] = 0x13; /* Request status. */ - cmd[2] = 0x00; /* From kernel. */ - cmd[3] = 0x80; /* Return card's DO. */ - cmd[4] = 0x00; - - buflen = DIM(buf); - - rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf); - if (rc || buflen < 2 || buf[buflen-2] != 0x90) - { - log_error ("ct_activate_card: can't get status of reader %d: %s\n", - slot, ct_error_string (rc)); - return SW_HOST_CARD_IO_ERROR; - } - - /* Connected, now activate the card. */ - dad[0] = 1; /* Destination address: CT. */ - sad[0] = 2; /* Source address: Host. */ - - cmd[0] = 0x20; /* Class byte. */ - cmd[1] = 0x12; /* Request ICC. */ - cmd[2] = 0x01; /* From first interface. */ - cmd[3] = 0x01; /* Return card's ATR. */ - cmd[4] = 0x00; - - buflen = DIM(buf); - - rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf); - if (rc || buflen < 2 || buf[buflen-2] != 0x90) - { - log_error ("ct_activate_card(%d): activation failed: %s\n", - slot, ct_error_string (rc)); - if (!rc) - log_printhex (" received data:", buf, buflen); - return SW_HOST_CARD_IO_ERROR; - } - - /* Store the type and the ATR. */ - if (buflen - 2 > DIM (reader_table[0].atr)) - { - log_error ("ct_activate_card(%d): ATR too long\n", slot); - return SW_HOST_CARD_IO_ERROR; - } - - memcpy (reader_table[slot].atr, buf, buflen - 2); - reader_table[slot].atrlen = buflen - 2; - return 0; -} - - -static int -close_ct_reader (int slot) -{ - CT_close (slot); - return 0; -} - -static int -reset_ct_reader (int slot) -{ - /* FIXME: Check is this is sufficient do do a reset. */ - return ct_activate_card (slot); -} - - -static int -ct_get_status (int slot, unsigned int *status, int on_wire) -{ - (void)slot; - (void)on_wire; - /* The status we returned is wrong but we don't care because ctAPI - is not anymore required. */ - *status = APDU_CARD_USABLE|APDU_CARD_PRESENT|APDU_CARD_ACTIVE; - return 0; -} - -/* Actually send the APDU of length APDULEN to SLOT and return a - maximum of *BUFLEN data in BUFFER, the actual returned size will be - set to BUFLEN. Returns: CT API error code. */ -static int -ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen, pininfo_t *pininfo) -{ - int rc; - unsigned char dad[1], sad[1]; - unsigned short ctbuflen; - - (void)pininfo; - - /* If we don't have an ATR, we need to reset the reader first. */ - if (!reader_table[slot].atrlen - && (rc = reset_ct_reader (slot))) - return rc; - - dad[0] = 0; /* Destination address: Card. */ - sad[0] = 2; /* Source address: Host. */ - ctbuflen = *buflen; - if (DBG_CARD_IO) - log_printhex (" CT_data:", apdu, apdulen); - rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer); - *buflen = ctbuflen; - - return rc? SW_HOST_CARD_IO_ERROR: 0; -} - - - -/* Open a reader and return an internal handle for it. PORT is a - non-negative value with the port number of the reader. USB readers - do have port numbers starting at 32769. */ -static int -open_ct_reader (int port) -{ - int rc, reader; - - if (port < 0 || port > 0xffff) - { - log_error ("open_ct_reader: invalid port %d requested\n", port); - return -1; - } - reader = new_reader_slot (); - if (reader == -1) - return reader; - reader_table[reader].port = port; - - rc = CT_init (reader, (unsigned short)port); - if (rc) - { - log_error ("apdu_open_ct_reader failed on port %d: %s\n", - port, ct_error_string (rc)); - reader_table[reader].used = 0; - unlock_slot (reader); - return -1; - } - - /* Only try to activate the card. */ - rc = ct_activate_card (reader); - if (rc) - { - reader_table[reader].atrlen = 0; - rc = 0; - } - - reader_table[reader].close_reader = close_ct_reader; - reader_table[reader].reset_reader = reset_ct_reader; - reader_table[reader].get_status_reader = ct_get_status; - reader_table[reader].send_apdu_reader = ct_send_apdu; - reader_table[reader].check_pinpad = NULL; - reader_table[reader].dump_status_reader = NULL; - reader_table[reader].pinpad_verify = NULL; - reader_table[reader].pinpad_modify = NULL; - - dump_reader_status (reader); - unlock_slot (reader); - return reader; -} - /* PC/SC Interface */ -#ifdef NEED_PCSC_WRAPPER -static int -writen (int fd, const void *buf, size_t nbytes) -{ - size_t nleft = nbytes; - int nwritten; - -/* log_printhex (" writen:", buf, nbytes); */ - - while (nleft > 0) - { -#ifdef USE_NPTH - nwritten = npth_write (fd, buf, nleft); -#else - nwritten = write (fd, buf, nleft); -#endif - if (nwritten < 0 && errno == EINTR) - continue; - if (nwritten < 0) - return -1; - nleft -= nwritten; - buf = (const char*)buf + nwritten; - } - return 0; -} - -/* Read up to BUFLEN bytes from FD and return the number of bytes - actually read in NREAD. Returns -1 on error or 0 on success. */ -static int -readn (int fd, void *buf, size_t buflen, size_t *nread) -{ - size_t nleft = buflen; - int n; -/* void *orig_buf = buf; */ - - while (nleft > 0) - { -#ifdef USE_NPTH -# ifdef HAVE_W32_SYSTEM -# error Cannot use npth_read here because it expects a system HANDLE. -# endif - n = npth_read (fd, buf, nleft); -#else - n = read (fd, buf, nleft); -#endif - if (n < 0 && errno == EINTR) - continue; - if (n < 0) - return -1; /* read error. */ - if (!n) - break; /* EOF */ - nleft -= n; - buf = (char*)buf + n; - } - if (nread) - *nread = buflen - nleft; - -/* log_printhex (" readn:", orig_buf, *nread); */ - - return 0; -} -#endif /*NEED_PCSC_WRAPPER*/ - static const char * pcsc_error_string (long err) { @@ -928,9 +643,8 @@ dump_pcsc_reader_status (int slot) } -#ifndef NEED_PCSC_WRAPPER static int -pcsc_get_status_direct (int slot, unsigned int *status, int on_wire) +pcsc_get_status (int slot, unsigned int *status, int on_wire) { long err; struct pcsc_readerstate_s rdrstates[1]; @@ -989,136 +703,15 @@ pcsc_get_status_direct (int slot, unsigned int *status, int on_wire) return 0; } -#endif /*!NEED_PCSC_WRAPPER*/ - - -#ifdef NEED_PCSC_WRAPPER -static int -pcsc_get_status_wrapped (int slot, unsigned int *status, int on_wire) -{ - long err; - reader_table_t slotp; - size_t len, full_len; - int i, n; - unsigned char msgbuf[9]; - unsigned char buffer[16]; - int sw = SW_HOST_CARD_IO_ERROR; - - (void)on_wire; - 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; - } - - 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 = buf_to_size_t (msgbuf+1); - 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 = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - { - log_error ("pcsc_status failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - /* This is a proper error code, so return immediately. */ - return pcsc_error_to_sw (err); - } - - full_len = len; - - /* The current version returns 3 words but we allow also for old - versions returning only 2 words. */ - n = 12 < len ? 12 : len; - if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) - || (len != 8 && len != 12)) - { - log_error ("error receiving PC/SC STATUS response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - - slotp->is_t0 = (len == 12 && !!(buffer[11] & PCSC_PROTOCOL_T0)); - - - 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; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return sw; -} -#endif /*NEED_PCSC_WRAPPER*/ +/* Send the APDU of length APDULEN to SLOT and return a maximum of + *BUFLEN data in BUFFER, the actual returned size will be stored at + BUFLEN. Returns: A status word. */ static int -pcsc_get_status (int slot, unsigned int *status, int on_wire) -{ -#ifdef NEED_PCSC_WRAPPER - return pcsc_get_status_wrapped (slot, status, on_wire); -#else - return pcsc_get_status_direct (slot, status, on_wire); -#endif -} - - -#ifndef NEED_PCSC_WRAPPER -static int -pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen, - pininfo_t *pininfo) +pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen, + pininfo_t *pininfo) { long err; struct pcsc_io_request_s send_pci; @@ -1149,270 +742,6 @@ pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen, return pcsc_error_to_sw (err); } -#endif /*!NEED_PCSC_WRAPPER*/ - - -#ifdef NEED_PCSC_WRAPPER -static int -pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen, - pininfo_t *pininfo) -{ - long err; - reader_table_t slotp; - size_t len, full_len; - int i, n; - unsigned char msgbuf[9]; - int sw = SW_HOST_CARD_IO_ERROR; - - (void)pininfo; - - if (!reader_table[slot].atrlen - && (err = reset_pcsc_reader (slot))) - return err; - - if (DBG_CARD_IO) - log_printhex (" PCSC_data:", apdu, apdulen); - - slotp = reader_table + slot; - - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 - || slotp->pcsc.pid == (pid_t)(-1) ) - { - log_error ("pcsc_send_apdu: pcsc-wrapper not running\n"); - return sw; - } - - msgbuf[0] = 0x03; /* TRANSMIT command. */ - len = apdulen; - msgbuf[1] = (len >> 24); - msgbuf[2] = (len >> 16); - msgbuf[3] = (len >> 8); - msgbuf[4] = (len ); - if ( writen (slotp->pcsc.req_fd, msgbuf, 5) - || writen (slotp->pcsc.req_fd, apdu, len)) - { - log_error ("error sending PC/SC TRANSMIT 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 TRANSMIT response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = buf_to_size_t (msgbuf+1); - 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 = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - { - log_error ("pcsc_transmit failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - return pcsc_error_to_sw (err); - } - - full_len = len; - - n = *buflen < len ? *buflen : len; - if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) - { - log_error ("error receiving PC/SC TRANSMIT response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - *buflen = n; - - full_len -= len; - if (full_len) - { - log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); - err = SW_HOST_INV_VALUE; - } - /* We need to read any rest of the response, to keep the - protocol running. */ - 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; - } - - return err; - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return sw; -} -#endif /*NEED_PCSC_WRAPPER*/ - - -/* Send the APDU of length APDULEN to SLOT and return a maximum of - *BUFLEN data in BUFFER, the actual returned size will be stored at - BUFLEN. Returns: A status word. */ -static int -pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen, - pininfo_t *pininfo) -{ -#ifdef NEED_PCSC_WRAPPER - return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo); -#else - return pcsc_send_apdu_direct (slot, apdu, apdulen, buffer, buflen, pininfo); -#endif -} - - -#ifndef NEED_PCSC_WRAPPER -static int -control_pcsc_direct (int slot, pcsc_dword_t ioctl_code, - const unsigned char *cntlbuf, size_t len, - unsigned char *buffer, pcsc_dword_t *buflen) -{ - long err; - - err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code, - cntlbuf, len, buffer, buflen? *buflen:0, buflen); - if (err) - { - log_error ("pcsc_control failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - return pcsc_error_to_sw (err); - } - - return 0; -} -#endif /*!NEED_PCSC_WRAPPER*/ - - -#ifdef NEED_PCSC_WRAPPER -static int -control_pcsc_wrapped (int slot, pcsc_dword_t ioctl_code, - const unsigned char *cntlbuf, size_t len, - unsigned char *buffer, pcsc_dword_t *buflen) -{ - long err = PCSC_E_NOT_TRANSACTED; - reader_table_t slotp; - unsigned char msgbuf[9]; - int i, n; - size_t full_len; - - slotp = reader_table + slot; - - msgbuf[0] = 0x06; /* CONTROL command. */ - msgbuf[1] = ((len + 4) >> 24); - msgbuf[2] = ((len + 4) >> 16); - msgbuf[3] = ((len + 4) >> 8); - msgbuf[4] = ((len + 4) ); - msgbuf[5] = (ioctl_code >> 24); - msgbuf[6] = (ioctl_code >> 16); - msgbuf[7] = (ioctl_code >> 8); - msgbuf[8] = (ioctl_code ); - if ( writen (slotp->pcsc.req_fd, msgbuf, 9) - || writen (slotp->pcsc.req_fd, cntlbuf, len)) - { - log_error ("error sending PC/SC CONTROL 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 CONTROL response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = buf32_to_size_t (msgbuf+1); - 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 = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - { - log_error ("pcsc_control failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - return pcsc_error_to_sw (err); - } - - full_len = len; - - if (buflen) - n = *buflen < len ? *buflen : len; - else - n = 0; - if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) - { - log_error ("error receiving PC/SC CONTROL response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - if (buflen) - *buflen = n; - - full_len -= len; - if (full_len) - { - log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); - err = PCSC_E_INVALID_VALUE; - } - /* We need to read any rest of the response, to keep the - protocol running. */ - 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 CONTROL response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - full_len -= n; - } - - if (!err) - return 0; - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return pcsc_error_to_sw (err); -} -#endif /*NEED_PCSC_WRAPPER*/ - /* Do some control with the value of IOCTL_CODE to the card inserted @@ -1425,106 +754,30 @@ control_pcsc (int slot, pcsc_dword_t ioctl_code, const unsigned char *cntlbuf, size_t len, unsigned char *buffer, pcsc_dword_t *buflen) { -#ifdef NEED_PCSC_WRAPPER - return control_pcsc_wrapped (slot, ioctl_code, cntlbuf, len, buffer, buflen); -#else - return control_pcsc_direct (slot, ioctl_code, cntlbuf, len, buffer, buflen); -#endif -} - - -#ifndef NEED_PCSC_WRAPPER -static int -close_pcsc_reader_direct (int slot) -{ - pcsc_release_context (reader_table[slot].pcsc.context); - return 0; -} -#endif /*!NEED_PCSC_WRAPPER*/ - - -#ifdef NEED_PCSC_WRAPPER -static int -close_pcsc_reader_wrapped (int slot) -{ long err; - reader_table_t slotp; - size_t len; - int i; - 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 ("close_pcsc_reader: pcsc-wrapper not running\n"); - return 0; - } - - msgbuf[0] = 0x02; /* CLOSE 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 CLOSE 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 CLOSE response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = buf32_to_size_t (msgbuf+1); - if (msgbuf[0] != 0x81 || len < 4) + err = pcsc_control (reader_table[slot].pcsc.card, ioctl_code, + cntlbuf, len, buffer, buflen? *buflen:0, buflen); + if (err) { - log_error ("invalid response header from PC/SC received\n"); - goto command_failed; + log_error ("pcsc_control failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return pcsc_error_to_sw (err); } - len -= 4; /* Already read the error code. */ - err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - log_error ("pcsc_close failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - /* We will close the wrapper in any case - errors are merely - informational. */ - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; return 0; } -#endif /*NEED_PCSC_WRAPPER*/ static int close_pcsc_reader (int slot) { -#ifdef NEED_PCSC_WRAPPER - return close_pcsc_reader_wrapped (slot); -#else - return close_pcsc_reader_direct (slot); -#endif + pcsc_release_context (reader_table[slot].pcsc.context); + return 0; } /* Connect a PC/SC card. */ -#ifndef NEED_PCSC_WRAPPER static int connect_pcsc_card (int slot) { @@ -1580,12 +833,8 @@ connect_pcsc_card (int slot) dump_reader_status (slot); return pcsc_error_to_sw (err); } -#endif /*!NEED_PCSC_WRAPPER*/ -/* Disconnect a PC/SC card. Note that this succeeds even if the card - is not connected. */ -#ifndef NEED_PCSC_WRAPPER static int disconnect_pcsc_card (int slot) { @@ -1606,12 +855,12 @@ disconnect_pcsc_card (int slot) reader_table[slot].pcsc.card = 0; return 0; } -#endif /*!NEED_PCSC_WRAPPER*/ -#ifndef NEED_PCSC_WRAPPER +/* Send an PC/SC reset command and return a status word on error or 0 + on success. */ static int -reset_pcsc_reader_direct (int slot) +reset_pcsc_reader (int slot) { int sw; @@ -1621,122 +870,6 @@ reset_pcsc_reader_direct (int slot) return sw; } -#endif /*NEED_PCSC_WRAPPER*/ - - -#ifdef NEED_PCSC_WRAPPER -static int -reset_pcsc_reader_wrapped (int slot) -{ - long err; - reader_table_t slotp; - size_t len; - int i, n; - unsigned char msgbuf[9]; - unsigned int dummy_status; - int sw = SW_HOST_CARD_IO_ERROR; - - 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; - } - - 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 = buf32_to_size_t (msgbuf+1); - 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=%lx)\n", - (unsigned long)len); - sw = SW_HOST_GENERAL_ERROR; - goto command_failed; - } - err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - { - log_error ("PC/SC RESET failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - /* If the error code is no smart card, we should not considere - this a major error and close the wrapper. */ - sw = pcsc_error_to_sw (err); - if (err == PCSC_E_NO_SMARTCARD) - return sw; - goto command_failed; - } - - /* The open function 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; - - /* Read the status so that IS_T0 will be set. */ - pcsc_get_status (slot, &dummy_status, 1); - - return 0; - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return sw; -} -#endif /* !NEED_PCSC_WRAPPER */ - - -/* Send an PC/SC reset command and return a status word on error or 0 - on success. */ -static int -reset_pcsc_reader (int slot) -{ -#ifdef NEED_PCSC_WRAPPER - return reset_pcsc_reader_wrapped (slot); -#else - return reset_pcsc_reader_direct (slot); -#endif -} /* Examine reader specific parameters and initialize. This is mostly @@ -1894,9 +1027,8 @@ pcsc_vendor_specific_init (int slot) /* Open the PC/SC reader without using the wrapper. Returns -1 on error or a slot number for the reader. */ -#ifndef NEED_PCSC_WRAPPER static int -open_pcsc_reader_direct (const char *portstr) +open_pcsc_reader (const char *portstr) { long err; int slot; @@ -1996,229 +1128,6 @@ open_pcsc_reader_direct (const char *portstr) unlock_slot (slot); return slot; } -#endif /*!NEED_PCSC_WRAPPER */ - - -/* Open the PC/SC reader using the pcsc_wrapper program. This is - needed to cope with different thread models and other peculiarities - of libpcsclite. */ -#ifdef NEED_PCSC_WRAPPER -static int -open_pcsc_reader_wrapped (const char *portstr) -{ - int slot; - reader_table_t slotp; - int fd, rp[2], wp[2]; - int n, i; - pid_t pid; - size_t len; - unsigned char msgbuf[9]; - int err; - unsigned int dummy_status; - - /* Note that we use the constant and not the function because this - code won't be used under Windows. */ - const char *wrapperpgm = GNUPG_LIBEXECDIR "/gnupg-pcsc-wrapper"; - - if (access (wrapperpgm, X_OK)) - { - log_error ("can't run PC/SC access module '%s': %s\n", - wrapperpgm, strerror (errno)); - return -1; - } - - slot = new_reader_slot (); - if (slot == -1) - return -1; - slotp = reader_table + slot; - - /* Fire up the PC/SCc wrapper. We don't use any fork/exec code from - the common directy but implement it directly so that this file - may still be source copied. */ - - if (pipe (rp) == -1) - { - log_error ("error creating a pipe: %s\n", strerror (errno)); - slotp->used = 0; - unlock_slot (slot); - return -1; - } - if (pipe (wp) == -1) - { - log_error ("error creating a pipe: %s\n", strerror (errno)); - close (rp[0]); - close (rp[1]); - slotp->used = 0; - unlock_slot (slot); - return -1; - } - - pid = fork (); - if (pid == -1) - { - log_error ("error forking process: %s\n", strerror (errno)); - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - slotp->used = 0; - unlock_slot (slot); - return -1; - } - slotp->pcsc.pid = pid; - - if (!pid) - { /* - === Child === - */ - - /* Double fork. */ - pid = fork (); - if (pid == -1) - _exit (31); - if (pid) - _exit (0); /* Immediate exit this parent, so that the child - gets cleaned up by the init process. */ - - /* Connect our pipes. */ - if (wp[0] != 0 && dup2 (wp[0], 0) == -1) - log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); - if (rp[1] != 1 && dup2 (rp[1], 1) == -1) - log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); - - /* Send stderr to the bit bucket. */ - fd = open ("/dev/null", O_WRONLY); - if (fd == -1) - log_fatal ("can't open '/dev/null': %s", strerror (errno)); - if (fd != 2 && dup2 (fd, 2) == -1) - log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); - - /* Close all other files. */ - close_all_fds (3, NULL); - - execl (wrapperpgm, - "pcsc-wrapper", - "--", - "1", /* API version */ - opt.pcsc_driver, /* Name of the PC/SC library. */ - NULL); - _exit (31); - } - - /* - === Parent === - */ - close (wp[0]); - close (rp[1]); - slotp->pcsc.req_fd = wp[1]; - slotp->pcsc.rsp_fd = rp[0]; - - /* Wait for the intermediate child to terminate. */ -#ifdef USE_NPTH -#define WAIT npth_waitpid -#else -#define WAIT waitpid -#endif - while ( (i=WAIT (pid, NULL, 0)) == -1 && errno == EINTR) - ; -#undef WAIT - - /* Now send the open request. */ - msgbuf[0] = 0x01; /* OPEN command. */ - len = portstr? strlen (portstr):0; - msgbuf[1] = (len >> 24); - msgbuf[2] = (len >> 16); - msgbuf[3] = (len >> 8); - msgbuf[4] = (len ); - if ( writen (slotp->pcsc.req_fd, msgbuf, 5) - || (portstr && writen (slotp->pcsc.req_fd, portstr, len))) - { - log_error ("error sending PC/SC OPEN 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 OPEN response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = buf32_to_size_t (msgbuf+1); - 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=%lx)\n", - (unsigned long)len); - goto command_failed; - } - err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5)); - if (err) - { - log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); - goto command_failed; - } - - /* The open request 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 OPEN response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - } - slotp->atrlen = len; - - reader_table[slot].close_reader = close_pcsc_reader; - reader_table[slot].reset_reader = reset_pcsc_reader; - reader_table[slot].get_status_reader = pcsc_get_status; - reader_table[slot].send_apdu_reader = pcsc_send_apdu; - reader_table[slot].dump_status_reader = dump_pcsc_reader_status; - - pcsc_vendor_specific_init (slot); - - /* Read the status so that IS_T0 will be set. */ - pcsc_get_status (slot, &dummy_status, 1); - - dump_reader_status (slot); - unlock_slot (slot); - return slot; - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - if (slotp->pcsc.pid != -1) - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - unlock_slot (slot); - /* There is no way to return SW. */ - return -1; - -} -#endif /*NEED_PCSC_WRAPPER*/ - - -static int -open_pcsc_reader (const char *portstr) -{ -#ifdef NEED_PCSC_WRAPPER - return open_pcsc_reader_wrapped (portstr); -#else - return open_pcsc_reader_direct (portstr); -#endif -} /* Check whether the reader supports the ISO command code COMMAND @@ -2998,45 +1907,15 @@ apdu_dev_list_finish (struct dev_list *dl) static int apdu_open_one_reader (const char *portstr) { - static int pcsc_api_loaded, ct_api_loaded; + static int pcsc_api_loaded; int slot; if (DBG_READER) log_debug ("enter: apdu_open_reader: portstr=%s\n", portstr); - if (opt.ctapi_driver && *opt.ctapi_driver) - { - int port = portstr? atoi (portstr) : 32768; - - if (!ct_api_loaded) - { - void *handle; - - handle = dlopen (opt.ctapi_driver, RTLD_LAZY); - if (!handle) - { - log_error ("apdu_open_reader: failed to open driver: %s\n", - dlerror ()); - return -1; - } - CT_init = dlsym (handle, "CT_init"); - CT_data = dlsym (handle, "CT_data"); - CT_close = dlsym (handle, "CT_close"); - if (!CT_init || !CT_data || !CT_close) - { - log_error ("apdu_open_reader: invalid CT-API driver\n"); - dlclose (handle); - return -1; - } - ct_api_loaded = 1; - } - return open_ct_reader (port); - } - - /* No ctAPI configured, so lets try the PC/SC API */ + /* Lets try the PC/SC API */ if (!pcsc_api_loaded) { -#ifndef NEED_PCSC_WRAPPER void *handle; handle = dlopen (opt.pcsc_driver, RTLD_LAZY); @@ -3115,7 +1994,6 @@ apdu_open_one_reader (const char *portstr) dlclose (handle); return -1; } -#endif /*!NEED_PCSC_WRAPPER*/ pcsc_api_loaded = 1; } @@ -3569,7 +2447,7 @@ static int apdu_get_status_internal (int slot, int hang, unsigned int *status, int on_wire) { int sw; - unsigned int s; + unsigned int s = 0; if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; @@ -3935,7 +2813,6 @@ send_le (int slot, int class, int ins, int p0, int p1, { xfree (apdu_buffer); apdu_buffer = NULL; - apdu_buffer_size = 0; } /* Store away the returned data but strip the statusword. */ |