[pkg-opensc-commit] [opensc] 21/50: reader: by default only short APDU supported
Eric Dorland
eric at moszumanska.debian.org
Sat May 28 03:35:48 UTC 2016
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository opensc.
commit e95b5151631f71fcee60a24d8d9d79f1c9719d8c
Author: Viktor Tarasov <viktor.tarasov at gmail.com>
Date: Tue Apr 19 13:24:09 2016 +0200
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
---
etc/opensc.conf.in | 6 ++--
src/libopensc/ctx.c | 29 ----------------
src/libopensc/opensc.h | 4 +++
src/libopensc/reader-ctapi.c | 34 +++++++++----------
src/libopensc/reader-openct.c | 7 ++++
src/libopensc/reader-pcsc.c | 78 ++++++++++++++++++++++++++++++-------------
6 files changed, 86 insertions(+), 72 deletions(-)
diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in
index 749bb52..1c2e8c5 100644
--- a/etc/opensc.conf.in
+++ b/etc/opensc.conf.in
@@ -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
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
index 03c92c7..8b2acf8 100644
--- a/src/libopensc/ctx.c
+++ b/src/libopensc/ctx.c
@@ -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;
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
index 728e8e4..c97154d 100644
--- a/src/libopensc/opensc.h
+++ b/src/libopensc/opensc.h
@@ -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;
diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c
index 9fa1f98..456edd3 100644
--- a/src/libopensc/reader-ctapi.c
+++ b/src/libopensc/reader-ctapi.c
@@ -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;
}
diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c
index b0e4f66..45d76b0 100644
--- a/src/libopensc/reader-openct.c
+++ b/src/libopensc/reader-openct.c
@@ -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);
diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c
index 4afc9b6..587f2b3 100644
--- a/src/libopensc/reader-pcsc.c
+++ b/src/libopensc/reader-pcsc.c
@@ -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);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git
More information about the pkg-opensc-commit
mailing list