Merge pull request #500 from frankmorgner/reader_max_data_size

honour PC/SC pt 10 dwMaxAPDUDataSize
This commit is contained in:
Frank Morgner 2015-07-31 15:35:32 +02:00
commit c48afdbfcb
5 changed files with 77 additions and 13 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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" */

View File

@ -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 {

View File

@ -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)