- made apdu_masquerade functionality available to all readers, not just pcsc
- added new parameters max_send_size and max_recv_size, roughly corresponding to the old max_le (SC_APDU_CHOP_SIZE) parameter. You can now set this chop limit per driver class (pcsc, openct, ctapi), which sets driver->max_{send,recv}_size. This value is copied to card->max_{send,recv}_size in sc_connect_card, and can be overridden by the card driver. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1683 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
af37c4e026
commit
5dda541b7e
|
@ -239,6 +239,10 @@ gpk_init(struct sc_card *card)
|
|||
/* State that we have an RNG */
|
||||
card->caps |= SC_CARD_CAP_RNG;
|
||||
|
||||
/* Make sure max send/receive size is 4 byte aligned. */
|
||||
card->max_send_size &= ~3;
|
||||
card->max_recv_size &= ~3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,10 @@ static int miocos_init(struct sc_card *card)
|
|||
|
||||
/* read_binary and friends shouldn't do more than 244 bytes
|
||||
* per operation */
|
||||
card->max_le = 244;
|
||||
if (card->max_send_size > 244)
|
||||
card->max_send_size = 244;
|
||||
if (card->max_recv_size > 244)
|
||||
card->max_recv_size = 244;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -253,7 +253,10 @@ static int starcos_init(struct sc_card *card)
|
|||
return SC_ERROR_INTERNAL;
|
||||
|
||||
/* we need read_binary&friends with max 128 bytes per read */
|
||||
card->max_le = 0x80;
|
||||
if (card->max_send_size > 128)
|
||||
card->max_send_size = 128;
|
||||
if (card->max_recv_size > 128)
|
||||
card->max_recv_size = 128;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,39 @@ static int sc_check_apdu(struct sc_context *ctx, const struct sc_apdu *apdu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle APDU masquerading
|
||||
*/
|
||||
static int
|
||||
sc_masquerade_apdu(sc_card_t *card, sc_apdu_t *apdu)
|
||||
{
|
||||
sc_context_t *ctx = card->reader->ctx;
|
||||
int masq = card->reader->driver->apdu_masquerade;
|
||||
int is_t0;
|
||||
|
||||
is_t0 = (card->slot->active_protocol == SC_PROTO_T0);
|
||||
|
||||
if (apdu->cse == SC_APDU_CASE_4_SHORT
|
||||
&& is_t0 && (masq & SC_APDU_MASQUERADE_4AS3)) {
|
||||
if (ctx->debug >= 5)
|
||||
sc_debug(ctx, "Masquerading case 4 APDU as case 3");
|
||||
apdu->cse = SC_APDU_CASE_3_SHORT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (apdu->cse == SC_APDU_CASE_1
|
||||
&& ((is_t0 && (masq & SC_APDU_MASQUERADE_1AS2))
|
||||
|| ((masq & SC_APDU_MASQUERADE_1AS2_ALWAYS)))) {
|
||||
if (ctx->debug >= 5)
|
||||
sc_debug(ctx, "Masquerading case 1 APDU as case 2");
|
||||
apdu->cse = SC_APDU_CASE_2_SHORT;
|
||||
apdu->le = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sc_transceive(struct sc_card *card, struct sc_apdu *apdu)
|
||||
{
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
@ -99,9 +132,21 @@ static int sc_transceive(struct sc_card *card, struct sc_apdu *apdu)
|
|||
size_t data_bytes = apdu->lc;
|
||||
int r;
|
||||
|
||||
#if 0
|
||||
if (card->ctx->debug >= 6)
|
||||
sc_debug(card->ctx, "masq=%x, max_send=%u, max_recv=%u",
|
||||
card->reader->driver->apdu_masquerade,
|
||||
card->max_recv_size,
|
||||
card->max_send_size);
|
||||
#endif
|
||||
|
||||
if (card->reader->ops->transmit == NULL)
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
assert(card->reader->ops->transmit != NULL);
|
||||
|
||||
/* APDU masquerading */
|
||||
if (card->reader->driver->apdu_masquerade)
|
||||
sc_masquerade_apdu(card, apdu);
|
||||
|
||||
if (data_bytes == 0)
|
||||
data_bytes = 256;
|
||||
*data++ = apdu->cla;
|
||||
|
@ -267,7 +312,6 @@ static struct sc_card * sc_card_new()
|
|||
free(card);
|
||||
return NULL;
|
||||
}
|
||||
card->max_le = SC_APDU_CHOP_SIZE;
|
||||
card->app_count = -1;
|
||||
card->magic = SC_CARD_MAGIC;
|
||||
card->mutex = sc_mutex_new();
|
||||
|
@ -317,6 +361,10 @@ int sc_connect_card(struct sc_reader *reader, int slot_id,
|
|||
card->slot = slot;
|
||||
card->ctx = ctx;
|
||||
|
||||
/* These can be overridden by the card driver */
|
||||
card->max_send_size = reader->driver->max_send_size;
|
||||
card->max_recv_size = reader->driver->max_recv_size;
|
||||
|
||||
memcpy(card->atr, slot->atr, slot->atr_len);
|
||||
card->atr_len = slot->atr_len;
|
||||
|
||||
|
@ -507,6 +555,7 @@ int sc_delete_file(struct sc_card *card, const struct sc_path *path)
|
|||
int sc_read_binary(struct sc_card *card, unsigned int idx,
|
||||
unsigned char *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_le = card->max_recv_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -516,14 +565,14 @@ int sc_read_binary(struct sc_card *card, unsigned int idx,
|
|||
return 0;
|
||||
if (card->ops->read_binary == NULL)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
|
||||
if (count > card->max_le) {
|
||||
if (count > max_le) {
|
||||
int bytes_read = 0;
|
||||
unsigned char *p = buf;
|
||||
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
int n = count > card->max_le ? card->max_le : count;
|
||||
int n = count > max_le ? max_le : count;
|
||||
r = sc_read_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
|
@ -548,6 +597,7 @@ int sc_read_binary(struct sc_card *card, unsigned int idx,
|
|||
int sc_write_binary(struct sc_card *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = card->max_send_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -557,14 +607,14 @@ int sc_write_binary(struct sc_card *card, unsigned int idx,
|
|||
return 0;
|
||||
if (card->ops->write_binary == NULL)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
|
||||
if (count > card->max_le) {
|
||||
if (count > max_lc) {
|
||||
int bytes_written = 0;
|
||||
const u8 *p = buf;
|
||||
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
int n = count > card->max_le ? card->max_le : count;
|
||||
int n = count > max_lc? max_lc : count;
|
||||
r = sc_write_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
|
@ -589,6 +639,7 @@ int sc_write_binary(struct sc_card *card, unsigned int idx,
|
|||
int sc_update_binary(struct sc_card *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = card->max_send_size;
|
||||
int r;
|
||||
|
||||
assert(card != NULL && card->ops != NULL && buf != NULL);
|
||||
|
@ -598,14 +649,14 @@ int sc_update_binary(struct sc_card *card, unsigned int idx,
|
|||
return 0;
|
||||
if (card->ops->update_binary == NULL)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
|
||||
if (count > card->max_le) {
|
||||
if (count > max_lc) {
|
||||
int bytes_written = 0;
|
||||
const u8 *p = buf;
|
||||
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
int n = count > card->max_le ? card->max_le : count;
|
||||
int n = count > max_lc? max_lc : count;
|
||||
r = sc_update_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
|
|
|
@ -27,6 +27,13 @@
|
|||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Default value for apdu_masquerade option */
|
||||
#ifndef _WIN32
|
||||
# define DEF_APDU_MASQ SC_APDU_MASQUERADE_NONE
|
||||
#else
|
||||
# define DEF_APDU_MASQ SC_APDU_MASQUERADE_4AS3
|
||||
#endif
|
||||
|
||||
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader)
|
||||
{
|
||||
assert(reader != NULL);
|
||||
|
@ -41,29 +48,29 @@ int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader)
|
|||
|
||||
struct _sc_driver_entry {
|
||||
char *name;
|
||||
void *func;
|
||||
struct sc_reader_driver *(*func)(void);
|
||||
char *libpath;
|
||||
struct sc_atr_table *atrs;
|
||||
unsigned int natrs;
|
||||
};
|
||||
|
||||
static const struct _sc_driver_entry internal_card_drivers[] = {
|
||||
{ "emv", (void *) sc_get_emv_driver, NULL },
|
||||
{ "etoken", (void *) sc_get_etoken_driver, NULL },
|
||||
{ "flex", (void *) sc_get_cryptoflex_driver, NULL },
|
||||
{ "cyberflex", (void *) sc_get_cyberflex_driver, NULL },
|
||||
{ "emv", sc_get_emv_driver, NULL },
|
||||
{ "etoken", sc_get_etoken_driver, NULL },
|
||||
{ "flex", sc_get_cryptoflex_driver, NULL },
|
||||
{ "cyberflex", sc_get_cyberflex_driver, NULL },
|
||||
#ifdef HAVE_OPENSSL
|
||||
{ "gpk", (void *) sc_get_gpk_driver, NULL },
|
||||
{ "gpk", sc_get_gpk_driver, NULL },
|
||||
#endif
|
||||
{ "miocos", (void *) sc_get_miocos_driver, NULL },
|
||||
{ "mcrd", (void *) sc_get_mcrd_driver, NULL },
|
||||
{ "setcos", (void *) sc_get_setcos_driver, NULL },
|
||||
{ "starcos", (void *) sc_get_starcos_driver, NULL },
|
||||
{ "tcos", (void *) sc_get_tcos_driver, NULL },
|
||||
{ "opengpg", (void *) sc_get_openpgp_driver, NULL },
|
||||
{ "miocos", sc_get_miocos_driver, NULL },
|
||||
{ "mcrd", sc_get_mcrd_driver, NULL },
|
||||
{ "setcos", sc_get_setcos_driver, NULL },
|
||||
{ "starcos", sc_get_starcos_driver, NULL },
|
||||
{ "tcos", sc_get_tcos_driver, NULL },
|
||||
{ "opengpg", sc_get_openpgp_driver, NULL },
|
||||
/* The default driver should be last, as it handles all the
|
||||
* unrecognized cards. */
|
||||
{ "default", (void *) sc_get_default_driver, NULL },
|
||||
{ "default", sc_get_default_driver, NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -224,6 +231,63 @@ static int load_parameters(struct sc_context *ctx, scconf_block *block,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void load_reader_driver_options(sc_context_t *ctx,
|
||||
struct sc_reader_driver *driver)
|
||||
{
|
||||
const char *name = driver->short_name;
|
||||
scconf_block *conf_block = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
|
||||
scconf_block **blocks;
|
||||
|
||||
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
|
||||
"reader_driver", name);
|
||||
conf_block = blocks[0];
|
||||
free(blocks);
|
||||
if (conf_block != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
driver->apdu_masquerade = DEF_APDU_MASQ;
|
||||
driver->max_send_size = SC_APDU_CHOP_SIZE;
|
||||
driver->max_recv_size = SC_APDU_CHOP_SIZE;
|
||||
if (conf_block != NULL) {
|
||||
const scconf_list *list;
|
||||
|
||||
if (scconf_get_bool(conf_block, "apdu_fix", 0))
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_4AS3;
|
||||
|
||||
list = scconf_find_list(conf_block, "apdu_masquerade");
|
||||
if (list)
|
||||
driver->apdu_masquerade = 0;
|
||||
for (; list; list = list->next) {
|
||||
if (!strcmp(list->data, "case4as3")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_4AS3;
|
||||
} else if (!strcmp(list->data, "case1as2")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_1AS2;
|
||||
} else if (!strcmp(list->data, "case1as2_always")) {
|
||||
driver->apdu_masquerade |= SC_APDU_MASQUERADE_1AS2_ALWAYS;
|
||||
} else if (!strcmp(list->data, "none")) {
|
||||
driver->apdu_masquerade = 0;
|
||||
} else {
|
||||
/* no match. Should something be logged? */
|
||||
sc_error(ctx,
|
||||
"Unexpected keyword \"%s\" in "
|
||||
"apdu_masquerade; ignored\n",
|
||||
list->data);
|
||||
}
|
||||
}
|
||||
|
||||
driver->max_send_size = scconf_get_int(conf_block,
|
||||
"max_send_size",
|
||||
SC_APDU_CHOP_SIZE);
|
||||
driver->max_recv_size = scconf_get_int(conf_block,
|
||||
"max_recv_size",
|
||||
SC_APDU_CHOP_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static int load_reader_drivers(struct sc_context *ctx,
|
||||
struct _sc_ctx_options *opts)
|
||||
{
|
||||
|
@ -234,13 +298,14 @@ static int load_reader_drivers(struct sc_context *ctx,
|
|||
for (drv_count = 0; ctx->reader_drivers[drv_count] != NULL; drv_count++);
|
||||
|
||||
for (i = 0; i < opts->rcount; i++) {
|
||||
const struct sc_reader_driver * (* func)(void) = NULL;
|
||||
struct sc_reader_driver *driver;
|
||||
struct sc_reader_driver * (*func)(void) = NULL;
|
||||
int j;
|
||||
|
||||
ent = &opts->rdrv[i];
|
||||
for (j = 0; internal_reader_drivers[j].name != NULL; j++)
|
||||
if (strcmp(ent->name, internal_reader_drivers[j].name) == 0) {
|
||||
func = (const struct sc_reader_driver * (*)(void)) internal_reader_drivers[j].func;
|
||||
func = (struct sc_reader_driver * (*)(void)) internal_reader_drivers[j].func;
|
||||
break;
|
||||
}
|
||||
if (func == NULL) {
|
||||
|
@ -250,8 +315,11 @@ static int load_reader_drivers(struct sc_context *ctx,
|
|||
ent->name);
|
||||
continue;
|
||||
}
|
||||
ctx->reader_drivers[drv_count] = func();
|
||||
ctx->reader_drivers[drv_count]->ops->init(ctx, &ctx->reader_drv_data[i]);
|
||||
driver = func();
|
||||
load_reader_driver_options(ctx, driver);
|
||||
driver->ops->init(ctx, &ctx->reader_drv_data[i]);
|
||||
|
||||
ctx->reader_drivers[drv_count] = driver;
|
||||
drv_count++;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -110,6 +110,7 @@ static int iso7816_read_binary(struct sc_card *card,
|
|||
u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int r;
|
||||
|
||||
assert(count <= card->max_recv_size);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0,
|
||||
(idx >> 8) & 0x7F, idx & 0xFF);
|
||||
apdu.le = count;
|
||||
|
@ -237,7 +238,7 @@ static int iso7816_write_binary(struct sc_card *card,
|
|||
struct sc_apdu apdu;
|
||||
int r;
|
||||
|
||||
assert(count <= card->max_le);
|
||||
assert(count <= card->max_send_size);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD0,
|
||||
(idx >> 8) & 0x7F, idx & 0xFF);
|
||||
apdu.lc = count;
|
||||
|
@ -258,7 +259,7 @@ static int iso7816_update_binary(struct sc_card *card,
|
|||
struct sc_apdu apdu;
|
||||
int r;
|
||||
|
||||
assert(count <= card->max_le);
|
||||
assert(count <= card->max_send_size);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
|
||||
(idx >> 8) & 0x7F, idx & 0xFF);
|
||||
apdu.lc = count;
|
||||
|
|
|
@ -257,7 +257,14 @@ struct sc_reader_driver {
|
|||
const char *name;
|
||||
const char *short_name;
|
||||
struct sc_reader_operations *ops;
|
||||
|
||||
size_t max_send_size, max_recv_size;
|
||||
int apdu_masquerade;
|
||||
};
|
||||
#define SC_APDU_MASQUERADE_NONE 0x00
|
||||
#define SC_APDU_MASQUERADE_4AS3 0x01
|
||||
#define SC_APDU_MASQUERADE_1AS2 0x02
|
||||
#define SC_APDU_MASQUERADE_1AS2_ALWAYS 0x04
|
||||
|
||||
/* slot flags */
|
||||
#define SC_SLOT_CARD_PRESENT 0x00000001
|
||||
|
@ -432,7 +439,8 @@ struct sc_card {
|
|||
int cla;
|
||||
u8 atr[SC_MAX_ATR_SIZE];
|
||||
size_t atr_len;
|
||||
size_t max_le;
|
||||
size_t max_send_size;
|
||||
size_t max_recv_size;
|
||||
|
||||
struct sc_app_info *app[SC_MAX_CARD_APPS];
|
||||
int app_count;
|
||||
|
@ -842,9 +850,9 @@ struct sc_card_error {
|
|||
|
||||
extern const char *sc_get_version(void);
|
||||
|
||||
extern const struct sc_reader_driver *sc_get_pcsc_driver(void);
|
||||
extern const struct sc_reader_driver *sc_get_ctapi_driver(void);
|
||||
extern const struct sc_reader_driver *sc_get_openct_driver(void);
|
||||
extern struct sc_reader_driver *sc_get_pcsc_driver(void);
|
||||
extern struct sc_reader_driver *sc_get_ctapi_driver(void);
|
||||
extern struct sc_reader_driver *sc_get_openct_driver(void);
|
||||
|
||||
extern struct sc_card_driver *sc_get_default_driver(void);
|
||||
extern struct sc_card_driver *sc_get_emv_driver(void);
|
||||
|
|
|
@ -204,7 +204,7 @@ static int ctapi_release(struct sc_reader *reader)
|
|||
|
||||
static struct sc_reader_operations ctapi_ops;
|
||||
|
||||
static const struct sc_reader_driver ctapi_drv = {
|
||||
static struct sc_reader_driver ctapi_drv = {
|
||||
"CT-API module",
|
||||
"ctapi",
|
||||
&ctapi_ops
|
||||
|
@ -362,7 +362,7 @@ static int ctapi_finish(struct sc_context *ctx, void *prv_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct sc_reader_driver * sc_get_ctapi_driver(void)
|
||||
struct sc_reader_driver * sc_get_ctapi_driver(void)
|
||||
{
|
||||
ctapi_ops.init = ctapi_init;
|
||||
ctapi_ops.finish = ctapi_finish;
|
||||
|
|
|
@ -427,7 +427,7 @@ openct_error(struct sc_reader *reader, int code)
|
|||
return SC_ERROR_READER;
|
||||
}
|
||||
|
||||
const struct sc_reader_driver *sc_get_openct_driver(void)
|
||||
struct sc_reader_driver *sc_get_openct_driver(void)
|
||||
{
|
||||
openct_ops.init = openct_reader_init;
|
||||
openct_ops.finish = openct_reader_finish;
|
||||
|
|
|
@ -56,26 +56,12 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define MASQUERADE_NONE 0x00
|
||||
#define MASQUERADE_4AS3 0x01
|
||||
#define MASQUERADE_1AS2 0x02
|
||||
#define MASQUERADE_1AS2_ALWAYS 0x04
|
||||
#define DO_MASQ(priv, mask) ((prv)->gpriv->apdu_masquerade & (mask))
|
||||
/* Default value for apdu_fix option */
|
||||
#ifndef _WIN32
|
||||
# define DEF_APDU_MASQ MASQUERADE_NONE
|
||||
#else
|
||||
# define DEF_APDU_MASQ MASQUERADE_4AS3
|
||||
#endif
|
||||
|
||||
#define GET_SLOT_PTR(s, i) (&(s)->slot[(i)])
|
||||
#define GET_PRIV_DATA(r) ((struct pcsc_private_data *) (r)->drv_data)
|
||||
#define GET_SLOT_DATA(r) ((struct pcsc_slot_data *) (r)->drv_data)
|
||||
|
||||
struct pcsc_global_private_data {
|
||||
SCARDCONTEXT pcsc_ctx;
|
||||
int apdu_masquerade; /* bitmask to indicate whether to
|
||||
'fix' some T=0 APDUs */
|
||||
};
|
||||
|
||||
struct pcsc_private_data {
|
||||
|
@ -144,10 +130,7 @@ static int pcsc_transmit(struct sc_reader *reader, struct sc_slot_info *slot,
|
|||
DWORD dwSendLength, dwRecvLength;
|
||||
LONG rv;
|
||||
SCARDHANDLE card;
|
||||
u8 masqueraded_apdu[5];
|
||||
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||
struct pcsc_private_data *prv = GET_PRIV_DATA(reader);
|
||||
int protocol = slot->active_protocol;
|
||||
|
||||
assert(pslot != NULL);
|
||||
card = pslot->pcsc_card;
|
||||
|
@ -157,40 +140,6 @@ static int pcsc_transmit(struct sc_reader *reader, struct sc_slot_info *slot,
|
|||
sRecvPci.dwProtocol = opensc_proto_to_pcsc(slot->active_protocol);
|
||||
sRecvPci.cbPciLength = sizeof(sRecvPci);
|
||||
|
||||
if (sendsize >= 6
|
||||
&& DO_MASQ(prv, MASQUERADE_4AS3) && protocol == SC_PROTO_T0) {
|
||||
/* Check if the APDU in question is of Case 4 */
|
||||
const u8 *p = sendbuf;
|
||||
int lc;
|
||||
|
||||
p += 4;
|
||||
lc = *p;
|
||||
if (lc == 0)
|
||||
lc = 256;
|
||||
if (sendsize == lc + 6) {
|
||||
/* Le is present, cut it out */
|
||||
if (reader->ctx->debug >= 5) {
|
||||
sc_debug(reader->ctx,
|
||||
"Removing Le byte from Case 4 APDU\n");
|
||||
}
|
||||
sendsize--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Masquerading case 1 APDUs */
|
||||
if (sendsize == 4
|
||||
&& (DO_MASQ(prv, MASQUERADE_1AS2_ALWAYS)
|
||||
|| (DO_MASQ(priv, MASQUERADE_1AS2) && protocol == SC_PROTO_T0))) {
|
||||
if (reader->ctx->debug >= 5) {
|
||||
sc_debug(reader->ctx,
|
||||
"Adding Lc byte to Case 1 APDU\n");
|
||||
}
|
||||
memcpy(masqueraded_apdu, sendbuf, 4);
|
||||
masqueraded_apdu[4] = 0;
|
||||
sendbuf = masqueraded_apdu;
|
||||
sendsize = 5;
|
||||
}
|
||||
|
||||
dwSendLength = sendsize;
|
||||
dwRecvLength = *recvsize;
|
||||
|
||||
|
@ -506,7 +455,7 @@ static int pcsc_release(struct sc_reader *reader)
|
|||
|
||||
static struct sc_reader_operations pcsc_ops;
|
||||
|
||||
static const struct sc_reader_driver pcsc_drv = {
|
||||
static struct sc_reader_driver pcsc_drv = {
|
||||
"PC/SC reader",
|
||||
"pcsc",
|
||||
&pcsc_ops
|
||||
|
@ -541,7 +490,6 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
|||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
gpriv->pcsc_ctx = pcsc_ctx;
|
||||
gpriv->apdu_masquerade = DEF_APDU_MASQ;
|
||||
*reader_data = gpriv;
|
||||
|
||||
reader_buf = (char *) malloc(sizeof(char) * reader_buf_size);
|
||||
|
@ -598,34 +546,6 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
|||
break;
|
||||
}
|
||||
|
||||
if (conf_block != NULL) {
|
||||
const scconf_list *list;
|
||||
|
||||
if (scconf_get_bool(conf_block, "apdu_fix", 0))
|
||||
gpriv->apdu_masquerade |= MASQUERADE_4AS3;
|
||||
|
||||
list = scconf_find_list(conf_block, "apdu_masquerade");
|
||||
if (list)
|
||||
gpriv->apdu_masquerade = 0;
|
||||
for (; list; list = list->next) {
|
||||
if (!strcmp(list->data, "case4as3")) {
|
||||
gpriv->apdu_masquerade |= MASQUERADE_4AS3;
|
||||
} else if (!strcmp(list->data, "case1as2")) {
|
||||
gpriv->apdu_masquerade |= MASQUERADE_1AS2;
|
||||
} else if (!strcmp(list->data, "case1as2_always")) {
|
||||
gpriv->apdu_masquerade |= MASQUERADE_1AS2_ALWAYS;
|
||||
} else if (!strcmp(list->data, "none")) {
|
||||
gpriv->apdu_masquerade = 0;
|
||||
} else {
|
||||
/* no match. Should something be logged? */
|
||||
sc_error(ctx,
|
||||
"Unexpected keyword \"%s\" in "
|
||||
"apdu_masquerade; ignored\n",
|
||||
list->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -641,7 +561,7 @@ static int pcsc_finish(struct sc_context *ctx, void *prv_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct sc_reader_driver * sc_get_pcsc_driver(void)
|
||||
struct sc_reader_driver * sc_get_pcsc_driver(void)
|
||||
{
|
||||
pcsc_ops.init = pcsc_init;
|
||||
pcsc_ops.finish = pcsc_finish;
|
||||
|
|
Loading…
Reference in New Issue