From 2d9802308f5c7b0190e73f3f5ac1b61345689148 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 26 Aug 2015 02:39:28 +0200 Subject: [PATCH 1/2] reactivate handling of `0` for max_recv/send_size The special value still needs to be handled for commands that are issued during card initialization. This especially concerns T=0 cards that need to use iso_get_response. fixes #533 regression of 85b79a33320b615c923a6a03b6d295d7543b3f55 --- src/libopensc/apdu.c | 2 +- src/libopensc/card-dnie.c | 2 +- src/libopensc/card-sc-hsm.c | 2 +- src/libopensc/card.c | 75 ++++++++++++++++++++++++++----------- src/libopensc/iso7816.c | 12 +++--- src/libopensc/opensc.h | 3 ++ 6 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c index 39c0294b..451c7063 100644 --- a/src/libopensc/apdu.c +++ b/src/libopensc/apdu.c @@ -581,7 +581,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu) * bytes using command chaining */ size_t len = apdu->datalen; const u8 *buf = apdu->data; - size_t max_send_size = card->max_send_size; + size_t max_send_size = sc_get_max_send_size(card); while (len != 0) { size_t plen; diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 90cb4241..0b25b845 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -871,7 +871,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa apdu.lc = pathlen; apdu.data = path; apdu.datalen = pathlen; - apdu.le = card->max_recv_size; + apdu.le = sc_get_max_recv_size(card); if (p1 == 3) apdu.cse= SC_APDU_CASE_1; diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index e4fab7bd..0613d49b 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -249,7 +249,7 @@ static int sc_hsm_read_binary(sc_card_t *card, cmdbuff[2] = (idx >> 8) & 0xFF; cmdbuff[3] = idx & 0xFF; - assert(count <= card->max_recv_size); + assert(count <= sc_get_max_recv_size(card)); sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00); apdu.data = cmdbuff; apdu.datalen = 4; diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 50da8ff8..1c7ae2fc 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -135,6 +135,54 @@ static void sc_card_free(sc_card_t *card) free(card); } +size_t sc_get_max_recv_size(const sc_card_t *card) +{ + size_t max_recv_size; + assert(card != NULL && card->reader != NULL); + max_recv_size = card->max_recv_size; + + /* initialize max_recv_size to a meaningfull value */ + if (card->caps & SC_CARD_CAP_APDU_EXT) { + if (!max_recv_size) + max_recv_size = 65536; + } else { + if (!max_recv_size) + max_recv_size = 256; + } + + /* Override card limitations with reader limitations. */ + if (card->reader->max_recv_size != 0 + && (card->reader->max_recv_size < card->max_recv_size)) + max_recv_size = card->reader->max_recv_size; + + return max_recv_size; +} + +size_t sc_get_max_send_size(const sc_card_t *card) +{ + size_t max_send_size; + + assert(card != NULL && card->reader != NULL); + + max_send_size = card->max_send_size; + + /* initialize max_send_size to a meaningfull value */ + if (card->caps & SC_CARD_CAP_APDU_EXT) { + if (!max_send_size) + max_send_size = 65535; + } else { + if (!max_send_size) + max_send_size = 255; + } + + /* Override card limitations with reader limitations. */ + if (card->reader->max_send_size != 0 + && (card->reader->max_send_size < card->max_send_size)) + max_send_size = card->reader->max_send_size; + + return max_send_size; +} + int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; @@ -252,25 +300,8 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) card->name = card->driver->name; /* initialize max_send_size/max_recv_size to a meaningfull value */ - if (card->caps & SC_CARD_CAP_APDU_EXT) { - if (!card->max_send_size) - card->max_send_size = 65535; - if (!card->max_recv_size) - card->max_recv_size = 65536; - } else { - if (!card->max_send_size) - card->max_send_size = 255; - if (!card->max_recv_size) - card->max_recv_size = 256; - } - - /* Override card limitations with reader limitations. */ - if (reader->max_recv_size != 0 - && (reader->max_recv_size < card->max_recv_size)) - card->max_recv_size = reader->max_recv_size; - if (reader->max_send_size != 0 - && (reader->max_send_size < card->max_send_size)) - card->max_send_size = reader->max_send_size; + card->max_recv_size = sc_get_max_recv_size(card); + card->max_send_size = sc_get_max_send_size(card); 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); @@ -489,7 +520,7 @@ int sc_delete_file(sc_card_t *card, const sc_path_t *path) int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { - size_t max_le = card->max_recv_size; + size_t max_le = sc_get_max_recv_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -539,7 +570,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx, int sc_write_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size; + size_t max_lc = sc_get_max_send_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -582,7 +613,7 @@ int sc_write_binary(sc_card_t *card, unsigned int idx, int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size; + size_t max_lc = sc_get_max_send_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 39b71868..01e4c1bb 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -35,15 +35,15 @@ static void fixup_transceive_length(const struct sc_card *card, { assert(card != NULL && apdu != NULL); - if (apdu->lc > card->max_send_size) { + if (apdu->lc > sc_get_max_send_size(card)) { /* The lower layers will automatically do chaining */ apdu->flags |= SC_APDU_FLAGS_CHAINING; } - if (apdu->le > card->max_recv_size) { + if (apdu->le > sc_get_max_recv_size(card)) { /* The lower layers will automatically do a GET RESPONSE, if possible. * All other workarounds must be carried out by the upper layers. */ - apdu->le = card->max_recv_size; + apdu->le = sc_get_max_recv_size(card); } } @@ -526,7 +526,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct apdu.p2 = 0; /* first record, return FCI */ apdu.resp = buf; apdu.resplen = sizeof(buf); - apdu.le = card->max_recv_size < 256 ? card->max_recv_size : 256; + apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256; } else { apdu.p2 = 0x0C; /* first record, return nothing */ @@ -719,8 +719,8 @@ iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf) size_t rlen; /* request at most max_recv_size bytes */ - if (*count > card->max_recv_size) - rlen = card->max_recv_size; + if (*count > sc_get_max_recv_size(card)) + rlen = sc_get_max_recv_size(card); else rlen = *count; diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index e9a4d19a..d7e89725 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -910,6 +910,9 @@ int sc_lock(struct sc_card *card); */ int sc_unlock(struct sc_card *card); +size_t sc_get_max_recv_size(const sc_card_t *card); +size_t sc_get_max_send_size(const sc_card_t *card); + /********************************************************************/ /* ISO 7816-4 related functions */ From fc02cb10931cb280a2e17e3a58697f7fefebbe75 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 26 Aug 2015 22:01:26 +0200 Subject: [PATCH 2/2] added documentation for sc_get_max_recv/send_size --- src/libopensc/opensc.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index d7e89725..febefa2d 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -910,7 +910,28 @@ int sc_lock(struct sc_card *card); */ int sc_unlock(struct sc_card *card); +/** + * @brief Calculate the maximum size of R-APDU payload (Ne). + * + * Takes card limitations into account such as extended length support as well + * as the reader's limitation for data transfer. + * + * @param card Initialized card object with its reader + * + * @return maximum Ne + */ size_t sc_get_max_recv_size(const sc_card_t *card); + +/** + * @brief Calculate the maximum size of C-APDU payload (Nc). + * + * Takes card limitations into account such as extended length support as well + * as the reader's limitation for data transfer. + * + * @param card + * + * @return maximum Nc + */ size_t sc_get_max_send_size(const sc_card_t *card);