diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 7daee5c5..2cb16f69 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -254,12 +254,12 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) * Note that zero means no limitations at all. */ if ((card->max_recv_size == 0) || - ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) - card->max_recv_size = reader->driver->max_recv_size; + ((reader->max_recv_size != 0) && (reader->max_recv_size < card->max_recv_size))) + card->max_recv_size = reader->max_recv_size; if ((card->max_send_size == 0) || - ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) - card->max_send_size = reader->driver->max_send_size; + ((reader->max_send_size != 0) && (reader->max_send_size < card->max_send_size))) + card->max_send_size = reader->max_send_size; sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 46700084..5595dc4f 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -289,15 +289,28 @@ static void load_reader_driver_options(sc_context_t *ctx) { struct sc_reader_driver *driver = ctx->reader_driver; scconf_block *conf_block = NULL; - - driver->max_send_size = 0; - driver->max_recv_size = 0; + 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) { - driver->max_send_size = scconf_get_int(conf_block, "max_send_size", driver->max_send_size); - driver->max_recv_size = scconf_get_int(conf_block, "max_recv_size", driver->max_recv_size); + 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); + } + } } } @@ -739,7 +752,6 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) ctx->reader_driver = sc_get_openct_driver(); #endif - load_reader_driver_options(ctx); r = ctx->reader_driver->ops->init(ctx); if (r != SC_SUCCESS) { sc_release_context(ctx); @@ -755,6 +767,7 @@ 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/internal-winscard.h b/src/libopensc/internal-winscard.h index 1e7bba14..2389d0c5 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -200,6 +200,7 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\ #define PCSCv2_PART10_PROPERTY_bMaxPINSize 7 #define PCSCv2_PART10_PROPERTY_sFirmwareID 8 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 +#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 /* structures used (but not defined) in PCSC Part 10: * "IFDs with Secure Pin Entry Capabilities" */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ad5405d5..8c4e81fa 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -275,8 +275,6 @@ struct sc_reader_driver { const char *short_name; struct sc_reader_operations *ops; - size_t max_send_size; /* Max Lc supported by the reader layer */ - size_t max_recv_size; /* Mac Le supported by the reader layer */ void *dll; }; @@ -305,6 +303,8 @@ typedef struct sc_reader { unsigned long flags, capabilities; unsigned int supported_protocols, active_protocol; + size_t max_send_size; /* Max Lc supported by the reader layer */ + size_t max_recv_size; /* Mac Le supported by the reader layer */ struct sc_atr atr; struct _atr_info { diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 73824525..666265d4 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -620,7 +620,7 @@ static struct sc_reader_driver pcsc_drv = { "PC/SC reader", "pcsc", &pcsc_ops, - 0, 0, NULL + NULL }; static int pcsc_init(sc_context_t *ctx) @@ -817,6 +817,50 @@ err: return flags; } +static int +part10_find_property_by_tag(unsigned char buffer[], int length, + int tag_searched); +/** + * @brief Detects reader's maximum data size + * + * @param reader reader to probe (\c get_tlv_properties must be initialized) + * + * @return maximum data size + */ +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; + int r; + + if (!reader) + goto err; + priv = GET_PRIV_DATA(reader); + if (!priv) + goto err; + + 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!"); + goto err; + } + + r = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize); + if (r >= 0) + max_data = r; + } + +err: + return max_data; +} + static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) { sc_context_t *ctx = reader->ctx; struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data; @@ -940,6 +984,12 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) sc_log(ctx, "%s %s", log_text, log_disabled); } } + + /* Set reader max_send_size and max_recv_size based on detected max_data */ + if (priv->get_tlv_properties) { + reader->max_send_size = part10_detect_max_data(reader, card_handle); + reader->max_recv_size = reader->max_send_size; + } } static int pcsc_detect_readers(sc_context_t *ctx)