[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