- move APDU encoding to the reader layer
- remove APDU masquerading code, it shouldn't be necessary anymore git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2831 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
85aaa4466d
commit
ca2a5e11fd
|
@ -34,7 +34,7 @@
|
|||
* @param proto the desired protocol
|
||||
* @return length of the encoded APDU
|
||||
*/
|
||||
static size_t sc_get_apdu_length(const sc_apdu_t *apdu, unsigned int proto)
|
||||
static size_t sc_apdu_get_length(const sc_apdu_t *apdu, unsigned int proto)
|
||||
{
|
||||
size_t ret = 4;
|
||||
|
||||
|
@ -80,7 +80,7 @@ static int sc_apdu2bytes(sc_context_t *ctx, const sc_apdu_t *apdu,
|
|||
{
|
||||
u8 *p = out;
|
||||
|
||||
size_t len = sc_get_apdu_length(apdu, proto);
|
||||
size_t len = sc_apdu_get_length(apdu, proto);
|
||||
|
||||
if (out == NULL || outlen < len)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
@ -168,139 +168,89 @@ static int sc_apdu2bytes(sc_context_t *ctx, const sc_apdu_t *apdu,
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static void sc_apdu_log_in(sc_context_t *ctx, const u8 *data, size_t len, int s)
|
||||
static void sc_apdu_log(sc_context_t *ctx, const u8 *data, size_t len,
|
||||
int is_sensitive, int is_outgoing)
|
||||
{
|
||||
size_t buflen = len * 5 + 128;
|
||||
char * buf = malloc(buflen);
|
||||
size_t blen = len * 5 + 128;
|
||||
char *buf = malloc(blen);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
if (s == 0 || ctx->debug >= 6)
|
||||
sc_hex_dump(ctx, data, len, buf, buflen);
|
||||
else
|
||||
snprintf(buf, buflen, "%02x %02x %02x %02x [sensitive data]\n",
|
||||
if (is_sensitive == 0 || ctx->debug >= 6)
|
||||
sc_hex_dump(ctx, data, len, buf, blen);
|
||||
else {
|
||||
if (is_outgoing != 0)
|
||||
/* is case of a outgoing APDU log the command header */
|
||||
snprintf(buf, blen, "%02x %02x %02x %02x "
|
||||
"[senstive data]\n",
|
||||
data[0], data[1], data[2], data[3]);
|
||||
else
|
||||
snprintf(buf, blen, "[sensitive data]\n");
|
||||
}
|
||||
|
||||
sc_debug(ctx,
|
||||
"\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %4d bytes send\n"
|
||||
sc_debug(ctx, "\n%s APDU data [%5u bytes] =====================================\n"
|
||||
"%s"
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n",
|
||||
(int)len, buf);
|
||||
|
||||
"======================================================================\n",
|
||||
is_outgoing != 0 ? "Outgoing" : "Incoming", len,
|
||||
buf);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void sc_apdu_log_out(sc_context_t *ctx, const u8 *data, size_t len, int s)
|
||||
int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf,
|
||||
size_t *len, unsigned int proto, int do_log)
|
||||
{
|
||||
size_t buflen = len * 5 + 128;
|
||||
char * buf = malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
size_t nlen;
|
||||
u8 *nbuf;
|
||||
|
||||
if (s == 0 || ctx->debug >= 6)
|
||||
sc_hex_dump(ctx, data, len, buf, buflen);
|
||||
else
|
||||
snprintf(buf, buflen, "[sensitive data]\n");
|
||||
if (apdu == NULL || buf == NULL || len == NULL)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
sc_debug(ctx,
|
||||
"\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< %4d bytes received\n"
|
||||
"%s"
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
|
||||
(int)len, buf);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/** Encodes the APDU in a octet buffer and sends it to the token
|
||||
* using the sc_reader_operations::transmit function.
|
||||
* @param card sc_card_t object of the token to which the APDU
|
||||
* should be sent
|
||||
* @param apdu sc_apdu_t object to transmit
|
||||
* @return SC_SUCCESS on success and an error code otherwise
|
||||
*/
|
||||
static int sc_apdu_encode_send(sc_card_t *card, sc_apdu_t *apdu,
|
||||
unsigned int proto)
|
||||
{
|
||||
size_t sendsize, recvsize, rbuflen = 0;
|
||||
u8 *sbuf = NULL, *rbuf = NULL;
|
||||
int r;
|
||||
sc_context_t *ctx = card->ctx;
|
||||
|
||||
if (card->reader->ops->transmit == NULL)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
|
||||
/* we always use a at least 258 byte size big return buffer
|
||||
* to mimic the behaviour of the old implementation (some readers
|
||||
* seems to require a larger than necessary return buffer).
|
||||
* The buffer for the returned data needs to be at least 2 bytes
|
||||
* larger than the expected data length to store SW1 and SW2. */
|
||||
recvsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2;
|
||||
rbuf = malloc(rbuflen);
|
||||
/* get the estimated length of encoded APDU */
|
||||
sendsize = sc_get_apdu_length(apdu, proto);
|
||||
if (sendsize == 0) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto out;
|
||||
}
|
||||
sbuf = malloc(sendsize);
|
||||
if (sbuf == NULL || rbuf == NULL) {
|
||||
r = SC_ERROR_MEMORY_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
nlen = sc_apdu_get_length(apdu, proto);
|
||||
if (nlen == 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
nbuf = malloc(nlen);
|
||||
if (nbuf == NULL)
|
||||
return SC_ERROR_MEMORY_FAILURE;
|
||||
/* encode the APDU in the buffer */
|
||||
r = sc_apdu2bytes(ctx, apdu, proto, sbuf, sendsize);
|
||||
if (r != SC_SUCCESS)
|
||||
goto out;
|
||||
if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS)
|
||||
return SC_ERROR_INTERNAL;
|
||||
*buf = nbuf;
|
||||
*len = nlen;
|
||||
|
||||
/* log outgoing APDU */
|
||||
#ifndef OPENSC_DONT_LOG_SENSITIVE
|
||||
if (ctx->debug >= 5)
|
||||
sc_apdu_log_in(ctx, sbuf, sendsize, (int)apdu->sensitive);
|
||||
#endif
|
||||
/* now let the reader driver transmit the APDU to the token */
|
||||
r = card->reader->ops->transmit(card->reader, card->slot, sbuf,
|
||||
sendsize, rbuf, &recvsize,
|
||||
apdu->control);
|
||||
if (r < 0) {
|
||||
/* unable to transmit ... most likely a reader problem */
|
||||
sc_error(ctx, "unable to transmit");
|
||||
goto out;
|
||||
}
|
||||
/* log incoming data */
|
||||
#ifndef OPENSC_DONT_LOG_SENSITIVE
|
||||
if (ctx->debug >= 5)
|
||||
sc_apdu_log_out(ctx, rbuf, recvsize, (int)apdu->sensitive);
|
||||
if (do_log != 0 && ctx->debug >= 5)
|
||||
sc_apdu_log(ctx, nbuf, nlen, apdu->sensitive, 1);
|
||||
#endif
|
||||
|
||||
if (recvsize < 2) {
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
|
||||
size_t len, int do_log)
|
||||
{
|
||||
#ifndef OPENSC_DONT_LOG_SENSITIVE
|
||||
if (do_log != 0 && ctx->debug >= 5)
|
||||
sc_apdu_log(ctx, buf, len, apdu->sensitive, 0);
|
||||
#endif
|
||||
if (len < 2) {
|
||||
/* no SW1 SW2 ... something went terrible wrong */
|
||||
sc_error(ctx, "SW1 SW2 missing");
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto out;
|
||||
sc_error(ctx, "invalid response: SW1 SW2 missing");
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
/* the last two bytes contain the status bytes SW1 and SW2 */
|
||||
apdu->sw1 = (unsigned int)rbuf[recvsize - 2];
|
||||
apdu->sw2 = (unsigned int)rbuf[recvsize - 1];
|
||||
recvsize -= 2;
|
||||
/* set the SW1 and SW2 status bytes (the last two bytes of
|
||||
* the response */
|
||||
apdu->sw1 = (unsigned int)buf[len - 2];
|
||||
apdu->sw2 = (unsigned int)buf[len - 1];
|
||||
len -= 2;
|
||||
/* set output length and copy the returned data if necessary */
|
||||
if (recvsize <= apdu->resplen)
|
||||
apdu->resplen = recvsize;
|
||||
if (len <= apdu->resplen)
|
||||
apdu->resplen = len;
|
||||
|
||||
if (apdu->resplen != 0)
|
||||
memcpy(apdu->resp, rbuf, apdu->resplen);
|
||||
memcpy(apdu->resp, buf, apdu->resplen);
|
||||
|
||||
r = SC_SUCCESS;
|
||||
out:
|
||||
if (sbuf != NULL) {
|
||||
sc_mem_clear(sbuf, sendsize);
|
||||
free(sbuf);
|
||||
}
|
||||
if (rbuf != NULL) {
|
||||
sc_mem_clear(rbuf, rbuflen);
|
||||
free(rbuf);
|
||||
}
|
||||
|
||||
return r;
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -456,7 +406,9 @@ static int do_single_transmit(sc_card_t *card, sc_apdu_t *apdu)
|
|||
*/
|
||||
|
||||
/* send APDU to the reader driver */
|
||||
r = sc_apdu_encode_send(card, apdu, card->slot->active_protocol);
|
||||
if (card->reader->ops->transmit == NULL)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
r = card->reader->ops->transmit(card->reader, card->slot, apdu);
|
||||
if (r != 0) {
|
||||
sc_error(ctx, "unable to transmit APDU");
|
||||
return r;
|
||||
|
|
|
@ -32,13 +32,6 @@
|
|||
#include <winreg.h>
|
||||
#endif
|
||||
|
||||
/* Default value for apdu_masquerade option */
|
||||
#ifndef _WIN32
|
||||
# define DEF_APDU_MASQ SC_APDU_MASQUERADE_NONE
|
||||
#else
|
||||
# define DEF_APDU_MASQ SC_APDU_MASQUERADE_4AS3
|
||||
#endif
|
||||
|
||||
int _sc_add_reader(sc_context_t *ctx, sc_reader_t *reader)
|
||||
{
|
||||
assert(reader != NULL);
|
||||
|
@ -260,33 +253,9 @@ static void load_reader_driver_options(sc_context_t *ctx,
|
|||
break;
|
||||
}
|
||||
|
||||
driver->apdu_masquerade = DEF_APDU_MASQ;
|
||||
driver->max_send_size = SC_APDU_CHOP_SIZE;
|
||||
driver->max_recv_size = SC_APDU_CHOP_SIZE;
|
||||
if (conf_block != NULL) {
|
||||
const scconf_list *list;
|
||||
|
||||
list = scconf_find_list(conf_block, "apdu_masquerade");
|
||||
if (list)
|
||||
driver->apdu_masquerade = 0;
|
||||
for (; list; list = list->next) {
|
||||
if (!strcmp(list->data, "case4as3")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_4AS3;
|
||||
} else if (!strcmp(list->data, "case1as2")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_1AS2;
|
||||
} else if (!strcmp(list->data, "case1as2_always")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_1AS2_ALWAYS;
|
||||
} else if (!strcmp(list->data, "none")) {
|
||||
driver->apdu_masquerade = 0;
|
||||
} else {
|
||||
/* no match. Should something be logged? */
|
||||
sc_error(ctx,
|
||||
"Unexpected keyword \"%s\" in "
|
||||
"apdu_masquerade; ignored\n",
|
||||
list->data);
|
||||
}
|
||||
}
|
||||
|
||||
driver->max_send_size = scconf_get_int(conf_block,
|
||||
"max_send_size",
|
||||
SC_APDU_CHOP_SIZE);
|
||||
|
|
|
@ -157,6 +157,33 @@ void sc_mutex_destroy(const sc_context_t *ctx, void *mutex);
|
|||
*/
|
||||
unsigned long sc_thread_id(const sc_context_t *ctx);
|
||||
|
||||
/********************************************************************/
|
||||
/* internal APDU handling functions */
|
||||
/********************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the encoded APDU in newly created buffer.
|
||||
* @param ctx sc_context_t object
|
||||
* @param apdu sc_apdu_t object with the APDU to encode
|
||||
* @param buf pointer to the newly allocated buffer
|
||||
* @param len length of the encoded APDU
|
||||
* @param proto protocol to be used
|
||||
* @param do_log log data to send
|
||||
* @return SC_SUCCESS on success and an error code otherwise
|
||||
*/
|
||||
int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf,
|
||||
size_t *len, unsigned int proto, int do_log);
|
||||
/**
|
||||
* Sets the status bytes and return data in the APDU
|
||||
* @param ctx sc_context_t object
|
||||
* @param apdu the apdu to which the data should be written
|
||||
* @param buf returned data
|
||||
* @param len length of the returned data
|
||||
* @param do_log log returned data
|
||||
* @return SC_SUCCESS on success and an error code otherwise
|
||||
*/
|
||||
int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
|
||||
size_t len, int do_log);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -265,13 +265,8 @@ struct sc_reader_driver {
|
|||
struct sc_reader_operations *ops;
|
||||
|
||||
size_t max_send_size, max_recv_size;
|
||||
int apdu_masquerade;
|
||||
void *dll;
|
||||
};
|
||||
#define SC_APDU_MASQUERADE_NONE 0x00
|
||||
#define SC_APDU_MASQUERADE_4AS3 0x01
|
||||
#define SC_APDU_MASQUERADE_1AS2 0x02
|
||||
#define SC_APDU_MASQUERADE_1AS2_ALWAYS 0x04
|
||||
|
||||
/* slot flags */
|
||||
#define SC_SLOT_CARD_PRESENT 0x00000001
|
||||
|
@ -386,9 +381,7 @@ struct sc_reader_operations {
|
|||
int (*disconnect)(struct sc_reader *reader, struct sc_slot_info *slot,
|
||||
int action);
|
||||
int (*transmit)(struct sc_reader *reader, struct sc_slot_info *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize,
|
||||
unsigned long control);
|
||||
sc_apdu_t *apdu);
|
||||
int (*lock)(struct sc_reader *reader, struct sc_slot_info *slot);
|
||||
int (*unlock)(struct sc_reader *reader, struct sc_slot_info *slot);
|
||||
int (*set_protocol)(struct sc_reader *reader, struct sc_slot_info *slot,
|
||||
|
|
|
@ -286,7 +286,7 @@ static int refresh_slot_attributes(sc_reader_t *reader,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ctapi_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
static int ctapi_internal_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize,
|
||||
unsigned long control)
|
||||
|
@ -315,6 +315,47 @@ static int ctapi_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ctapi_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
sc_apdu_t *apdu)
|
||||
{
|
||||
size_t ssize, rsize, rbuflen = 0;
|
||||
u8 *sbuf = NULL, *rbuf = NULL;
|
||||
int r;
|
||||
|
||||
rsize = rbuflen = apdu->resplen + 2;
|
||||
rbuf = malloc(rbuflen);
|
||||
if (rbuf == NULL) {
|
||||
r = SC_ERROR_MEMORY_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
/* encode and log the APDU */
|
||||
r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
goto out;
|
||||
r = ctapi_internal_transmit(reader, slot, sbuf, ssize,
|
||||
rbuf, &rsize, apdu->control);
|
||||
if (r < 0) {
|
||||
/* unable to transmit ... most likely a reader problem */
|
||||
sc_error(reader->ctx, "unable to transmit");
|
||||
goto out;
|
||||
}
|
||||
/* log and set response */
|
||||
r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
return r;
|
||||
out:
|
||||
if (sbuf != NULL) {
|
||||
sc_mem_clear(sbuf, ssize);
|
||||
free(sbuf);
|
||||
}
|
||||
if (rbuf != NULL) {
|
||||
sc_mem_clear(rbuf, rbuflen);
|
||||
free(rbuf);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ctapi_detect_card_presence(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||
{
|
||||
int r;
|
||||
|
@ -411,7 +452,7 @@ static struct sc_reader_driver ctapi_drv = {
|
|||
"CT-API module",
|
||||
"ctapi",
|
||||
&ctapi_ops,
|
||||
0, 0, 0, NULL
|
||||
0, 0, NULL
|
||||
};
|
||||
|
||||
static struct ctapi_module * add_module(struct ctapi_global_private_data *gpriv,
|
||||
|
|
|
@ -43,9 +43,7 @@ static int openct_reader_connect(sc_reader_t *reader,
|
|||
static int openct_reader_disconnect(sc_reader_t *reader,
|
||||
sc_slot_info_t *slot, int action);
|
||||
static int openct_reader_transmit(sc_reader_t *reader,
|
||||
sc_slot_info_t *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize, unsigned long control);
|
||||
sc_slot_info_t *slot, sc_apdu_t *apdu);
|
||||
static int openct_reader_perform_verify(sc_reader_t *reader,
|
||||
sc_slot_info_t *slot,
|
||||
struct sc_pin_cmd_data *info);
|
||||
|
@ -61,7 +59,7 @@ static struct sc_reader_driver openct_reader_driver = {
|
|||
"OpenCT reader",
|
||||
"openct",
|
||||
&openct_ops,
|
||||
0, 0, 0, NULL
|
||||
0, 0, NULL
|
||||
};
|
||||
|
||||
/* private data structures */
|
||||
|
@ -287,7 +285,7 @@ openct_reader_disconnect(sc_reader_t *reader,
|
|||
}
|
||||
|
||||
int
|
||||
openct_reader_transmit(sc_reader_t *reader,
|
||||
openct_reader_internal_transmit(sc_reader_t *reader,
|
||||
sc_slot_info_t *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize, unsigned long control)
|
||||
|
@ -315,6 +313,48 @@ openct_reader_transmit(sc_reader_t *reader,
|
|||
return openct_error(reader, rc);
|
||||
}
|
||||
|
||||
static int openct_reader_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
sc_apdu_t *apdu)
|
||||
{
|
||||
size_t ssize, rsize, rbuflen = 0;
|
||||
u8 *sbuf = NULL, *rbuf = NULL;
|
||||
int r;
|
||||
|
||||
rsize = rbuflen = apdu->resplen + 2;
|
||||
rbuf = malloc(rbuflen);
|
||||
if (rbuf == NULL) {
|
||||
r = SC_ERROR_MEMORY_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
/* encode and log the APDU */
|
||||
r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
goto out;
|
||||
r = openct_reader_internal_transmit(reader, slot, sbuf, ssize,
|
||||
rbuf, &rsize, apdu->control);
|
||||
if (r < 0) {
|
||||
/* unable to transmit ... most likely a reader problem */
|
||||
sc_error(reader->ctx, "unable to transmit");
|
||||
goto out;
|
||||
}
|
||||
/* log and set response */
|
||||
r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
return r;
|
||||
out:
|
||||
if (sbuf != NULL) {
|
||||
sc_mem_clear(sbuf, ssize);
|
||||
free(sbuf);
|
||||
}
|
||||
if (rbuf != NULL) {
|
||||
sc_mem_clear(rbuf, rbuflen);
|
||||
free(rbuf);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
openct_reader_perform_verify(sc_reader_t *reader,
|
||||
sc_slot_info_t *slot,
|
||||
|
|
|
@ -141,7 +141,7 @@ static DWORD opensc_proto_to_pcsc(unsigned int proto)
|
|||
}
|
||||
}
|
||||
|
||||
static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
static int pcsc_internal_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
const u8 *sendbuf, size_t sendsize,
|
||||
u8 *recvbuf, size_t *recvsize,
|
||||
unsigned long control)
|
||||
|
@ -202,6 +202,53 @@ static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pcsc_transmit(sc_reader_t *reader, sc_slot_info_t *slot,
|
||||
sc_apdu_t *apdu)
|
||||
{
|
||||
size_t ssize, rsize, rbuflen = 0;
|
||||
u8 *sbuf = NULL, *rbuf = NULL;
|
||||
int r;
|
||||
|
||||
/* we always use a at least 258 byte size big return buffer
|
||||
* to mimic the behaviour of the old implementation (some readers
|
||||
* seems to require a larger than necessary return buffer).
|
||||
* The buffer for the returned data needs to be at least 2 bytes
|
||||
* larger than the expected data length to store SW1 and SW2. */
|
||||
rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2;
|
||||
rbuf = malloc(rbuflen);
|
||||
if (rbuf == NULL) {
|
||||
r = SC_ERROR_MEMORY_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
/* encode and log the APDU */
|
||||
r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, slot->active_protocol, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
goto out;
|
||||
r = pcsc_internal_transmit(reader, slot, sbuf, ssize,
|
||||
rbuf, &rsize, apdu->control);
|
||||
if (r < 0) {
|
||||
/* unable to transmit ... most likely a reader problem */
|
||||
sc_error(reader->ctx, "unable to transmit");
|
||||
goto out;
|
||||
}
|
||||
/* log and set response */
|
||||
r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize, 1);
|
||||
if (r != SC_SUCCESS)
|
||||
return r;
|
||||
out:
|
||||
if (sbuf != NULL) {
|
||||
sc_mem_clear(sbuf, ssize);
|
||||
free(sbuf);
|
||||
}
|
||||
if (rbuf != NULL) {
|
||||
sc_mem_clear(rbuf, rbuflen);
|
||||
free(rbuf);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int refresh_slot_attributes(sc_reader_t *reader, sc_slot_info_t *slot)
|
||||
{
|
||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||
|
@ -586,7 +633,7 @@ static struct sc_reader_driver pcsc_drv = {
|
|||
"PC/SC reader",
|
||||
"pcsc",
|
||||
&pcsc_ops,
|
||||
0, 0, 0, NULL
|
||||
0, 0, NULL
|
||||
};
|
||||
|
||||
static int pcsc_init(sc_context_t *ctx, void **reader_data)
|
||||
|
|
Loading…
Reference in New Issue