Skip to content

Commit

Permalink
honour PC/SC pt 10 dwMaxAPDUDataSize
Browse files Browse the repository at this point in the history
closes OpenSC#306
  • Loading branch information
Frank Morgner committed Jul 28, 2015
1 parent 7eb62a0 commit c92e3b4
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 13 deletions.
8 changes: 4 additions & 4 deletions src/libopensc/card.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 19 additions & 6 deletions src/libopensc/ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/libopensc/internal-winscard.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" */
Expand Down
4 changes: 2 additions & 2 deletions src/libopensc/opensc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down Expand Up @@ -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 {
Expand Down
52 changes: 51 additions & 1 deletion src/libopensc/reader-pcsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -817,6 +817,50 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader, SCARDH
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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit c92e3b4

Please sign in to comment.