reader: by default only short APDU supported
default values of reader's max send/receive sizes correspond to only short APDU supported; these values can be overwritten by reader itself with the proper value of dwMaxAPDUDataSize from TLV properties, or with the corresponding options in OpenSC configuration. resolves issue #735
This commit is contained in:
parent
41f34fdbcf
commit
e95b515163
|
@ -66,9 +66,9 @@ app default {
|
|||
# The following section shows definitions for PC/SC readers.
|
||||
reader_driver pcsc {
|
||||
# Limit command and response sizes.
|
||||
# Default: n/a
|
||||
# max_send_size = 255;
|
||||
# max_recv_size = 256;
|
||||
# Default: max_send_size = 255, max_recv_size = 256;
|
||||
# max_send_size = 0;
|
||||
# max_recv_size = 0;
|
||||
#
|
||||
# Connect to reader in exclusive mode?
|
||||
# Default: false
|
||||
|
|
|
@ -356,34 +356,6 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options *
|
|||
return err;
|
||||
}
|
||||
|
||||
static void load_reader_driver_options(sc_context_t *ctx)
|
||||
{
|
||||
struct sc_reader_driver *driver = ctx->reader_driver;
|
||||
scconf_block *conf_block = NULL;
|
||||
sc_reader_t *reader;
|
||||
int max_send_size;
|
||||
int max_recv_size;
|
||||
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", driver->short_name, 1);
|
||||
|
||||
if (conf_block != NULL) {
|
||||
max_send_size = scconf_get_int(conf_block, "max_send_size", -1);
|
||||
max_recv_size = scconf_get_int(conf_block, "max_recv_size", -1);
|
||||
if (max_send_size >= 0 || max_recv_size >= 0) {
|
||||
if (list_iterator_start(&ctx->readers)) {
|
||||
reader = list_iterator_next(&ctx->readers);
|
||||
while (reader) {
|
||||
if (max_send_size >= 0)
|
||||
reader->max_send_size = max_send_size;
|
||||
if (max_recv_size >= 0)
|
||||
reader->max_recv_size = max_recv_size;
|
||||
reader = list_iterator_next(&ctx->readers);
|
||||
}
|
||||
list_iterator_stop(&ctx->readers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find library module for provided driver in configuration file
|
||||
|
@ -824,7 +796,6 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
|
|||
}
|
||||
del_drvs(&opts);
|
||||
sc_ctx_detect_readers(ctx);
|
||||
load_reader_driver_options(ctx);
|
||||
*ctx_out = ctx;
|
||||
|
||||
return SC_SUCCESS;
|
||||
|
|
|
@ -294,6 +294,10 @@ struct sc_reader_driver {
|
|||
#define SC_READER_CAP_PACE_DESTROY_CHANNEL 0x00000010
|
||||
#define SC_READER_CAP_PACE_GENERIC 0x00000020
|
||||
|
||||
/* reader send/receive length of short APDU */
|
||||
#define SC_READER_SHORT_APDU_MAX_SEND_SIZE 255
|
||||
#define SC_READER_SHORT_APDU_MAX_RECV_SIZE 256
|
||||
|
||||
typedef struct sc_reader {
|
||||
struct sc_context *ctx;
|
||||
const struct sc_reader_driver *driver;
|
||||
|
|
|
@ -322,20 +322,18 @@ static struct ctapi_module * add_module(struct ctapi_global_private_data *gpriv,
|
|||
}
|
||||
|
||||
static int ctapi_load_module(sc_context_t *ctx,
|
||||
struct ctapi_global_private_data *gpriv,
|
||||
scconf_block *conf)
|
||||
struct ctapi_global_private_data *gpriv, scconf_block *conf)
|
||||
{
|
||||
const char *val;
|
||||
struct ctapi_functions funcs;
|
||||
struct ctapi_module *mod;
|
||||
const scconf_list *list;
|
||||
scconf_block *conf_block = NULL;
|
||||
void *dlh;
|
||||
int r, i, NumUnits;
|
||||
u8 cmd[5], rbuf[256], sad, dad;
|
||||
unsigned short lr;
|
||||
|
||||
|
||||
|
||||
list = scconf_find_list(conf, "ports");
|
||||
if (list == NULL) {
|
||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "No ports configured.\n");
|
||||
|
@ -391,6 +389,16 @@ static int ctapi_load_module(sc_context_t *ctx,
|
|||
reader->name = strdup(namebuf);
|
||||
priv->funcs = funcs;
|
||||
priv->ctn = mod->ctn_count;
|
||||
|
||||
reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE;
|
||||
reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE;
|
||||
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "ctapi", 1);
|
||||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
}
|
||||
|
||||
r = _sc_add_reader(ctx, reader);
|
||||
if (r) {
|
||||
funcs.CT_close((unsigned short)mod->ctn_count);
|
||||
|
@ -506,21 +514,13 @@ static int ctapi_init(sc_context_t *ctx)
|
|||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
ctx->reader_drv_data = gpriv;
|
||||
|
||||
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
|
||||
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
|
||||
"reader_driver", "ctapi");
|
||||
if (blocks && blocks[0])
|
||||
conf_block = blocks[0];
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "ctapi", 1);
|
||||
if (conf_block) {
|
||||
blocks = scconf_find_blocks(ctx->conf, conf_block, "module", NULL);
|
||||
for (i = 0; blocks != NULL && blocks[i] != NULL; i++)
|
||||
ctapi_load_module(ctx, gpriv, blocks[i]);
|
||||
free(blocks);
|
||||
if (conf_block != NULL)
|
||||
break;
|
||||
}
|
||||
if (conf_block == NULL)
|
||||
return 0;
|
||||
blocks = scconf_find_blocks(ctx->conf, conf_block, "module", NULL);
|
||||
for (i = 0; blocks != NULL && blocks[i] != NULL; i++)
|
||||
ctapi_load_module(ctx, gpriv, blocks[i]);
|
||||
free(blocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ static int
|
|||
openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
|
||||
{
|
||||
sc_reader_t *reader;
|
||||
scconf_block *conf_block;
|
||||
struct driver_data *data;
|
||||
int rc;
|
||||
|
||||
|
@ -119,6 +120,12 @@ openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
|
|||
reader->drv_data = data;
|
||||
reader->name = strdup(data->info.ct_name);
|
||||
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "openct", 1);
|
||||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
}
|
||||
|
||||
if ((rc = _sc_add_reader(ctx, reader)) < 0) {
|
||||
free(data);
|
||||
free(reader->name);
|
||||
|
|
|
@ -704,8 +704,10 @@ static int pcsc_init(sc_context_t *ctx)
|
|||
gpriv->provider_library =
|
||||
scconf_get_str(conf_block, "provider_library", gpriv->provider_library);
|
||||
}
|
||||
sc_log(ctx, "PC/SC options: connect_exclusive=%d disconnect_action=%d transaction_end_action=%d reconnect_action=%d enable_pinpad=%d enable_pace=%d",
|
||||
gpriv->connect_exclusive, gpriv->disconnect_action, gpriv->transaction_end_action, gpriv->reconnect_action, gpriv->enable_pinpad, gpriv->enable_pace);
|
||||
sc_log(ctx, "PC/SC options: connect_exclusive=%d disconnect_action=%d transaction_end_action=%d"
|
||||
" reconnect_action=%d enable_pinpad=%d enable_pace=%d",
|
||||
gpriv->connect_exclusive, gpriv->disconnect_action, gpriv->transaction_end_action,
|
||||
gpriv->reconnect_action, gpriv->enable_pinpad, gpriv->enable_pace);
|
||||
|
||||
gpriv->dlhandle = sc_dlopen(gpriv->provider_library);
|
||||
if (gpriv->dlhandle == NULL) {
|
||||
|
@ -870,31 +872,32 @@ part10_find_property_by_tag(unsigned char buffer[], int length,
|
|||
*/
|
||||
static size_t part10_detect_max_data(sc_reader_t *reader, SCARDHANDLE card_handle)
|
||||
{
|
||||
u8 rbuf[256];
|
||||
DWORD rcount = sizeof rbuf;
|
||||
struct pcsc_private_data *priv;
|
||||
/* 0 means no limitations */
|
||||
size_t max_data = 0;
|
||||
u8 rbuf[256];
|
||||
DWORD rcount = sizeof rbuf;
|
||||
struct pcsc_private_data *priv = NULL;
|
||||
/* 0 means extended APDU not supported */
|
||||
size_t max_data = 0;
|
||||
int r;
|
||||
|
||||
if (!reader)
|
||||
goto err;
|
||||
priv = GET_PRIV_DATA(reader);
|
||||
if (!priv)
|
||||
goto err;
|
||||
if (!reader)
|
||||
goto err;
|
||||
priv = GET_PRIV_DATA(reader);
|
||||
if (!priv)
|
||||
goto err;
|
||||
|
||||
if (priv->get_tlv_properties && priv->gpriv) {
|
||||
if (priv->get_tlv_properties && priv->gpriv) {
|
||||
if (SCARD_S_SUCCESS != priv->gpriv->SCardControl(card_handle,
|
||||
priv->get_tlv_properties, NULL, 0, rbuf, sizeof(rbuf),
|
||||
&rcount)) {
|
||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL,
|
||||
"PC/SC v2 part 10: Get TLV properties failed!");
|
||||
priv->get_tlv_properties, NULL, 0, rbuf, sizeof(rbuf), &rcount)) {
|
||||
sc_log(reader->ctx, "PC/SC v2 part 10: Get TLV properties failed!");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = part10_find_property_by_tag(rbuf, rcount,
|
||||
PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize);
|
||||
if (r >= 0)
|
||||
sc_log(reader->ctx, "get dwMaxAPDUDataSize property returned %i", r);
|
||||
|
||||
/* 256 < X <= 0x10000: short and extended APDU of up to X bytes of data */
|
||||
if (r > 0x100 && r <= 0x10000)
|
||||
max_data = r;
|
||||
}
|
||||
|
||||
|
@ -1058,11 +1061,13 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
|
|||
}
|
||||
|
||||
if (priv->get_tlv_properties) {
|
||||
/* Set reader max_send_size and max_recv_size based on
|
||||
/* Try to set reader max_send_size and max_recv_size based on
|
||||
* detected max_data */
|
||||
reader->max_send_size = part10_detect_max_data(reader,
|
||||
card_handle);
|
||||
reader->max_recv_size = reader->max_send_size;
|
||||
int max_data = part10_detect_max_data(reader, card_handle);
|
||||
if (max_data > 0) {
|
||||
reader->max_send_size = max_data;
|
||||
reader->max_recv_size = max_data;
|
||||
}
|
||||
|
||||
/* debug the product and vendor ID of the reader */
|
||||
part10_get_vendor_product(reader, card_handle, NULL, NULL);
|
||||
|
@ -1171,6 +1176,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||
for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) {
|
||||
sc_reader_t *reader = NULL, *old_reader;
|
||||
struct pcsc_private_data *priv = NULL;
|
||||
scconf_block *conf_block = NULL;
|
||||
int found = 0;
|
||||
|
||||
for (i=0;i < sc_ctx_get_reader_count(ctx) && !found;i++) {
|
||||
|
@ -1196,7 +1202,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||
ret = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err1;
|
||||
}
|
||||
if ((priv = calloc(1, sizeof(struct pcsc_private_data))) == NULL) {
|
||||
if ((priv = calloc(1, sizeof(struct pcsc_private_data))) == NULL) {
|
||||
ret = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err1;
|
||||
}
|
||||
|
@ -1208,6 +1214,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||
ret = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
priv->gpriv = gpriv;
|
||||
if (_sc_add_reader(ctx, reader)) {
|
||||
ret = SC_SUCCESS; /* silent ignore */
|
||||
|
@ -1238,10 +1245,25 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
|||
PCSC_TRACE(reader, "SCardConnect(SHARED)", rv);
|
||||
}
|
||||
|
||||
/* max send/receive sizes: with default values only short APDU supported */
|
||||
reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE;
|
||||
reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE;
|
||||
|
||||
/* max send/receive sizes: check if reader explicitely declares support of extended APDU */
|
||||
if (rv == SCARD_S_SUCCESS) {
|
||||
detect_reader_features(reader, card_handle);
|
||||
gpriv->SCardDisconnect(card_handle, SCARD_LEAVE_CARD);
|
||||
}
|
||||
|
||||
/* max send/receive sizes: if exist in configuration these options overwrite
|
||||
* the values by default and values declared by reader */
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "pcsc", 1);
|
||||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
}
|
||||
|
||||
sc_log(ctx, "reader's max-send-size: %i, max-recv-size: %i", reader->max_send_size, reader->max_recv_size);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -2257,6 +2279,7 @@ int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcs
|
|||
SCARDHANDLE card_handle;
|
||||
u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
PCSC_TLV_STRUCTURE *pcsc_tlv;
|
||||
scconf_block *conf_block = NULL;
|
||||
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
|
||||
LONG rv;
|
||||
char reader_name[128];
|
||||
|
@ -2318,6 +2341,15 @@ int cardmod_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcs
|
|||
}
|
||||
priv->gpriv = gpriv;
|
||||
|
||||
reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE;
|
||||
reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE;
|
||||
|
||||
conf_block = sc_get_conf_block(ctx, "reader_driver", "cardmod", 1);
|
||||
if (conf_block) {
|
||||
reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size);
|
||||
reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size);
|
||||
}
|
||||
|
||||
/* attempt to detect protocol in use T0/T1/RAW */
|
||||
rv = priv->gpriv->SCardStatus(card_handle, NULL, &readers_len,
|
||||
&state, &prot, atr, &atr_len);
|
||||
|
|
Loading…
Reference in New Issue