From 56c376489f4544d3f09bb71de675621ca51e6b12 Mon Sep 17 00:00:00 2001 From: adminmt Date: Mon, 15 Jun 2015 14:56:47 +0200 Subject: [PATCH 01/20] ATR update card-masktech.c, customactions.cpp changed atqb + mask of MaskTech smart card (a) and (c) removed MaskTech smart card (d) added atr mask to MaskTech smart card (a) and (b) --- src/libopensc/card-masktech.c | 10 +++++----- win32/customactions.cpp | 14 ++++++-------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c index 2b036e75..1fab31fb 100644 --- a/src/libopensc/card-masktech.c +++ b/src/libopensc/card-masktech.c @@ -32,13 +32,13 @@ #include "iso7816.h" static struct sc_atr_table masktech_atrs[] = { - {"3B:89:80:01:4D:54:43:4F:53:70:02:02:05:3B", NULL, NULL, + {"3B:89:80:01:4D:54:43:4F:53:70:02:00:04:31", + "FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:FF:FC:F4:F5" , NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:88:80:01:00:00:00:00:77:81:81:00:7E", NULL, NULL, + {"3B:88:80:01:00:00:00:00:77:81:80:00:6E", "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:EE:FF:EE", NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:02:05:41", NULL, NULL, - SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:01:02:45", NULL, NULL, + {"3B:9D:13:81:31:60:35:80:31:C0:69:4D:54:43:4F:53:73:02:00:00:40", + "FF:FF:FF:FF:FF:FF:FD:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:F0:F0", NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, {NULL, NULL, NULL, 0, 0, NULL} }; diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 988e1ffd..5da7ec91 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -78,14 +78,12 @@ MD_REGISTRATION minidriver_registration[] = { 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, /* from card-masktech.c */ /* note: the card name MUST be unique */ - {TEXT("MaskTech smart card (a)"), {0x3b,0x89,0x80,0x01,0x4d,0x54,0x43,0x4f,0x53,0x70,0x02,0x02,0x05,0x3b}, - 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x02,0x05,0x41}, - 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (c)"), {0x3B,0x88,0x80,0x01,0x00,0x00,0x00,0x00,0x77,0x81,0x81,0x00,0x7E}, - 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (d)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x01,0x02,0x45}, - 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("MaskTech smart card (a)"), {0x3b,0x89,0x80,0x01,0x4d,0x54,0x43,0x4f,0x53,0x70,0x02,0x00,0x04,0x31}, + 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xff,0xfc,0xf4,0xf5}}, + {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x35,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x00,0x00,0x40}, + 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xf0,0xf0}}, + {TEXT("MaskTech smart card (c)"), {0x3B,0x88,0x80,0x01,0x00,0x00,0x00,0x00,0x77,0x81,0x80,0x00,0x6E}, + 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xee,0xff,0xee}}, }; From 5a11d0e2fd9c7734dcc11352483b6d4f7f9291b5 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Fri, 21 Aug 2015 18:51:30 +0100 Subject: [PATCH 02/20] Add support for C_GetTokenInfo pin status flags for ISO7816 cards This is already supported for a couple of the card drivers, but since it's a general feature of ISO7816 it should go in iso7816.c, rather than the current situation where identical code for this is copy and pasted in each driver. However, some cards apparently don't support this feature and count it as a failed PIN attempt, so I've added a flag for now to indicate whether the card supports this feature. It future, it could be moved to blacklist cards rather than whitelist them, subject to more testing. --- src/libopensc/card-myeid.c | 43 +------------------------------------ src/libopensc/card-sc-hsm.c | 36 +------------------------------ src/libopensc/iso7816.c | 41 +++++++++++++++++++++++++++++------ src/libopensc/opensc.h | 3 +++ 4 files changed, 39 insertions(+), 84 deletions(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 9d6417f1..ead6ba9a 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -170,7 +170,7 @@ static int myeid_init(struct sc_card *card) #endif /* State that we have an RNG */ - card->caps |= SC_CARD_CAP_RNG; + card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; card->max_recv_size = 255; card->max_send_size = 255; @@ -524,42 +524,6 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path) LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); } -static int myeid_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data, - int *tries_left) -{ - sc_apdu_t apdu; - int r; - - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference); - - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - - if (r == SC_ERROR_PIN_CODE_INCORRECT) { - data->pin1.tries_left = apdu.sw2 & 0xF; - r = SC_SUCCESS; - } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { - data->pin1.tries_left = 0; - r = SC_SUCCESS; - } - LOG_TEST_RET(card->ctx, r, "Check SW error"); - - if (r == SC_SUCCESS) - { - data->pin1.pad_length = data->pin2.pad_length = 8; - data->pin1.pad_char = data->pin2.pad_char = 0xFF; - } - - - if (tries_left != NULL) { - *tries_left = data->pin1.tries_left; - } - - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); -} - static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { @@ -567,11 +531,6 @@ static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, LOG_FUNC_CALLED(card->ctx); - if (data->cmd == SC_PIN_CMD_GET_INFO) - { - return myeid_pin_info(card, data, tries_left); - } - sc_log(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n", data->pin_reference, data->pin1.len, data->pin2.len); diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 87d563b2..b02c84e0 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -137,37 +137,6 @@ static int sc_hsm_match_card(struct sc_card *card) -static int sc_hsm_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data, - int *tries_left) -{ - sc_apdu_t apdu; - int r; - - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference); - - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - - if (r == SC_ERROR_PIN_CODE_INCORRECT) { - data->pin1.tries_left = apdu.sw2 & 0xF; - r = SC_SUCCESS; - } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { - data->pin1.tries_left = 0; - r = SC_SUCCESS; - } - LOG_TEST_RET(card->ctx, r, "Check SW error"); - - if (tries_left != NULL) { - *tries_left = data->pin1.tries_left; - } - - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); -} - - - /* * Encode 16 hexadecimals of SO-PIN into binary form * Caller must check length of sopin and provide an 8 byte buffer @@ -206,9 +175,6 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; int r; - if (data->cmd == SC_PIN_CMD_GET_INFO) { - return sc_hsm_pin_info(card, data, tries_left); - } if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) { if (data->pin1.len != 16) return SC_ERROR_INVALID_PIN_LENGTH; @@ -1058,7 +1024,7 @@ static int sc_hsm_init(struct sc_card *card) _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); _sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL); - card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT; + card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO; card->max_send_size = 1431; // 1439 buffer size - 8 byte TLV because of odd ins in UPDATE BINARY card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index baa15814..d0bf8b4f 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -987,6 +987,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len) { int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0; + int cse = SC_APDU_CASE_3_SHORT; switch (data->pin_type) { case SC_AC_CHV: @@ -1052,11 +1053,16 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, p1 |= 0x01; } break; + case SC_PIN_CMD_GET_INFO: + ins = 0x20; + /* No data to send or to receive */ + cse = SC_APDU_CASE_1; + break; default: return SC_ERROR_NOT_SUPPORTED; } - sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, p1, data->pin_reference); + sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference); apdu->lc = len; apdu->datalen = len; apdu->data = buf; @@ -1076,6 +1082,16 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l if (tries_left) *tries_left = -1; + /* Many cards do support PIN status queries, but some cards don't and + * mistakenly count the command as a failed PIN attempt, so for now we + * whitelist cards with this flag. In future this may be reduced to a + * blacklist, subject to testing more cards. */ + if (data->cmd == SC_PIN_CMD_GET_INFO && + !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) { + sc_log(card->ctx, "Card does not support PIN status queries"); + return SC_ERROR_NOT_SUPPORTED; + } + /* See if we've been called from another card driver, which is * passing an APDU to us (this allows to write card drivers * whose PIN functions behave "mostly like ISO" except in some @@ -1089,7 +1105,7 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l } apdu = data->apdu; - if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) { + if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) { /* Transmit the APDU to the card */ r = sc_transmit_apdu(card, apdu); @@ -1119,12 +1135,23 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l data->apdu = NULL; LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (apdu->sw1 == 0x63) { - if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL) - *tries_left = apdu->sw2 & 0x0F; - return SC_ERROR_PIN_CODE_INCORRECT; + r = sc_check_sw(card, apdu->sw1, apdu->sw2); + + if (data->cmd == SC_PIN_CMD_GET_INFO) { + if (r == SC_ERROR_PIN_CODE_INCORRECT) { + data->pin1.tries_left = apdu->sw2 & 0xF; + r = SC_SUCCESS; + } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { + data->pin1.tries_left = 0; + r = SC_SUCCESS; + } + + if (tries_left != NULL) { + *tries_left = data->pin1.tries_left; + } } - return sc_check_sw(card, apdu->sw1, apdu->sw2); + + return r; } diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index e9a4d19a..69fdd34a 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -439,6 +439,9 @@ struct sc_reader_operations { /* Card has on-board random number source. */ #define SC_CARD_CAP_RNG 0x00000004 +/* Card supports ISO7816 PIN status queries using an empty VERIFY */ +#define SC_CARD_CAP_ISO7816_PIN_INFO 0x00000008 + /* Use the card's ACs in sc_pkcs15init_authenticate(), * instead of relying on the ACL info in the profile files. */ #define SC_CARD_CAP_USE_FCI_AC 0x00000010 From 2897e6fb5cbb78696a887c68a675c696957bb455 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Sun, 23 Aug 2015 22:33:50 +0100 Subject: [PATCH 03/20] Leniently interpret the ISO7816 return codes in card-piv.c This adds support for the Yubikey NEO. I'm not sure whether it breaks the specification, or follows some other version of the spec, but in my testing it returns SW1=0x63, SW2=0x0N for N PIN tries remaining. Ignoring the top nibble seems a harmless change to the behaviour to support this device. --- src/libopensc/card-piv.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index c12c9bd4..218d74d3 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -2895,7 +2895,7 @@ static int piv_init(sc_card_t *card) _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); - card->caps |= SC_CARD_CAP_RNG; + card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; /* * 800-73-3 cards may have a history object and/or a discovery object @@ -2912,6 +2912,27 @@ static int piv_init(sc_card_t *card) } +static int piv_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2) +{ + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + + const u8 *yubikey_neo_atr = + (const u8*)"\x3B\xFC\x13\x00\x00\x81\x31\xFE\x15\x59\x75\x62\x69\x6B\x65\x79\x4E\x45\x4F\x72\x33\xE1"; + if (card->atr.len != 22 || memcmp(card->atr.value, yubikey_neo_atr, 22) != 0) + return iso_drv->ops->check_sw(card, sw1, sw2); + + /* Handle here the Yubikey NEO, which returns 0x0X rather than 0xCX to + * indicate the number of remaining PIN retries. Perhaps they misread the + * spec and thought 0xCX meant "clear" or "don't care", not a literal 0xC! */ + if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0x00U && sw2 != 0) { + sc_log(card->ctx, "Verification failed (remaining tries: %d)", (sw2 & 0x0f)); + return SC_ERROR_PIN_CODE_INCORRECT; + } + + return iso_drv->ops->check_sw(card, sw1, sw2); +} + + static int piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { @@ -2952,6 +2973,7 @@ static struct sc_card_driver * sc_get_driver(void) piv_ops.restore_security_env = piv_restore_security_env; piv_ops.compute_signature = piv_compute_signature; piv_ops.decipher = piv_decipher; + piv_ops.check_sw = piv_check_sw; piv_ops.card_ctl = piv_card_ctl; piv_ops.pin_cmd = piv_pin_cmd; From 2d9802308f5c7b0190e73f3f5ac1b61345689148 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 26 Aug 2015 02:39:28 +0200 Subject: [PATCH 04/20] 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 05/20] 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); From 8da31d271e2f29e6ce67fcf4886301f2b5a7f1d2 Mon Sep 17 00:00:00 2001 From: Martin Paljak Date: Sun, 30 Aug 2015 18:58:00 +0300 Subject: [PATCH 06/20] Fix for #183: export more symbols - also export C_Initialize and C_Finalize to please vmware-view - have a single pkcs11.exports file for both pkcs11-spy and opensc-pkcs11 --- src/pkcs11/Makefile.am | 10 +++++----- src/pkcs11/Makefile.mak | 6 +++--- src/pkcs11/opensc-pkcs11.exports | 1 - src/pkcs11/pkcs11-spy.exports | 1 - src/pkcs11/pkcs11.exports | 3 +++ 5 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 src/pkcs11/opensc-pkcs11.exports delete mode 100644 src/pkcs11/pkcs11-spy.exports create mode 100644 src/pkcs11/pkcs11.exports diff --git a/src/pkcs11/Makefile.am b/src/pkcs11/Makefile.am index c8ed808e..aac6739c 100644 --- a/src/pkcs11/Makefile.am +++ b/src/pkcs11/Makefile.am @@ -12,7 +12,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src OPENSC_PKCS11_INC = sc-pkcs11.h pkcs11.h pkcs11-opensc.h OPENSC_PKCS11_SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \ mechanism.c openssl.c framework-pkcs15.c \ - framework-pkcs15init.c debug.c opensc-pkcs11.exports \ + framework-pkcs15init.c debug.c pkcs11.exports \ pkcs11-display.c pkcs11-display.h OPENSC_PKCS11_LIBS = \ $(top_builddir)/src/libopensc/libopensc.la \ @@ -23,23 +23,23 @@ OPENSC_PKCS11_LIBS = \ opensc_pkcs11_la_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC) opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/opensc-pkcs11.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined onepin_opensc_pkcs11_la_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC) onepin_opensc_pkcs11_la_CFLAGS = -DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" onepin_opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) onepin_opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/opensc-pkcs11.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined -pkcs11_spy_la_SOURCES = pkcs11-spy.c pkcs11-display.c pkcs11-display.h pkcs11-spy.exports +pkcs11_spy_la_SOURCES = pkcs11-spy.c pkcs11-display.c pkcs11-display.h pkcs11.exports pkcs11_spy_la_LIBADD = \ $(top_builddir)/src/common/libpkcs11.la \ $(top_builddir)/src/common/libscdl.la \ $(OPTIONAL_OPENSSL_LIBS) pkcs11_spy_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/pkcs11-spy.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined if WIN32 diff --git a/src/pkcs11/Makefile.mak b/src/pkcs11/Makefile.mak index e3cdfbda..7fcdb930 100644 --- a/src/pkcs11/Makefile.mak +++ b/src/pkcs11/Makefile.mak @@ -16,14 +16,14 @@ all: versioninfo-pkcs11.res $(TARGET1) $(TARGET2) $(TARGET3) versioninfo-pkcs11- $(TARGET1): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type opensc-pkcs11.exports >> $*.def + type pkcs11.exports >> $*.def link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET1) $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(OPENSSL_LIB) gdi32.lib if EXIST $(TARGET1).manifest mt -manifest $(TARGET1).manifest -outputresource:$(TARGET1);2 $(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type opensc-pkcs11.exports >> $*.def + type pkcs11.exports >> $*.def del pkcs11-global.obj cl $(CODE_OPTIMIZATION) $(COPTS) /DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" /c pkcs11-global.c link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET2) $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(OPENSSL_LIB) gdi32.lib @@ -32,6 +32,6 @@ $(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(TARGET3): $(OBJECTS3) ..\libopensc\opensc.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type $*.exports >> $*.def + type pkcs11.exports >> $*.def link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET3) $(OBJECTS3) ..\libopensc\opensc.lib ..\common\libpkcs11.lib ..\common\libscdl.lib $(OPENSSL_LIB) gdi32.lib advapi32.lib if EXIST $(TARGET3).manifest mt -manifest $(TARGET3).manifest -outputresource:$(TARGET3);2 diff --git a/src/pkcs11/opensc-pkcs11.exports b/src/pkcs11/opensc-pkcs11.exports deleted file mode 100644 index 562ecea2..00000000 --- a/src/pkcs11/opensc-pkcs11.exports +++ /dev/null @@ -1 +0,0 @@ -C_GetFunctionList diff --git a/src/pkcs11/pkcs11-spy.exports b/src/pkcs11/pkcs11-spy.exports deleted file mode 100644 index 562ecea2..00000000 --- a/src/pkcs11/pkcs11-spy.exports +++ /dev/null @@ -1 +0,0 @@ -C_GetFunctionList diff --git a/src/pkcs11/pkcs11.exports b/src/pkcs11/pkcs11.exports new file mode 100644 index 00000000..edc62c26 --- /dev/null +++ b/src/pkcs11/pkcs11.exports @@ -0,0 +1,3 @@ +C_GetFunctionList +C_Initialize +C_Finalize From c9efb2f643fa0706c753f7b2f8ac7dbd45211581 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Thu, 5 Feb 2015 19:18:05 +0100 Subject: [PATCH 07/20] make file cache dir configurable in cases where you use pam_pkcs11, HOME might not be set so paths based on $HOME are not usable, so that the combination of home and caching does not work. Having the paths configurable (together with a good setting of access rights) resolves that problem. --- etc/opensc.conf.in | 6 ++++++ src/libopensc/ctx.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index c14107a8..a270308d 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -431,6 +431,12 @@ app default { # Default: false # use_file_caching = true; # + # set a path for caching + # so you do not use the env variables and for pam_pkcs11 + # (with certificate check) where $HOME is not set + # Default: path in user home + # file_cache_dir = /var/lib/opensc/cache + # # Use PIN caching? # Default: true # use_pin_caching = false; diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 15312f7e..c7154344 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -880,9 +880,18 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize) { char *homedir; const char *cache_dir; + scconf_block *conf_block = NULL; #ifdef _WIN32 char temp_path[PATH_MAX]; #endif + conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1); + cache_dir = scconf_get_str(conf_block, "file_cache_dir", NULL); + if (cache_dir != NULL) { + if (bufsize <= strlen(cache_dir)) + return SC_ERROR_BUFFER_TOO_SMALL; + strcpy(buf, cache_dir); + return SC_SUCCESS; + } #ifndef _WIN32 cache_dir = ".eid/cache"; From 9456db90fc0a2039567e2851e7ec537c479aa06b Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 24 Jan 2015 21:43:15 +0100 Subject: [PATCH 08/20] handle record-based files correctly when doing file caching implementation copied from `sc_pkcs15_read_file` closes #372 --- src/tools/pkcs15-tool.c | 46 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 4b0cbd85..f7cc6469 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -1564,11 +1564,47 @@ static int read_and_cache_file(const sc_path_t *path) printf("out of memory!"); return -1; } - r = sc_read_binary(card, 0, buf, size, 0); - if (r < 0) { - fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); - free(buf); - return -1; + if (tfile->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV) { + int i; + size_t l, record_len; + unsigned char *head = buf; + + for (i=1; ; i++) { + l = size - (head - buf); + if (l > 256) { l = 256; } + r = sc_read_record(p15card->card, i, head, l, SC_RECORD_BY_REC_NR); + if (r == SC_ERROR_RECORD_NOT_FOUND) { + r = 0; + break; + } + if (r < 0) { + free(buf); + return -1; + } + if (r < 2) + break; + record_len = head[1]; + if (record_len != 0xff) { + memmove(head,head+2,r-2); + head += (r-2); + } + else { + if (r < 4) + break; + memmove(head,head+4,r-4); + head += (r-4); + } + } + r = head - buf; + + } else { + + r = sc_read_binary(card, 0, buf, size, 0); + if (r < 0) { + fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); + free(buf); + return -1; + } } r = sc_pkcs15_cache_file(p15card, path, buf, r); if (r) { From cf2a9cbbb042538121b2deb0feaeca33fd5b5925 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 12 Aug 2015 00:22:20 +0200 Subject: [PATCH 09/20] added call back for getting vendor/product id implementation taken from https://github.com/jasp00/OpenSC/commit/83142d4caeae5958850795757c7d6c5cf072a15c --- src/libopensc/internal-winscard.h | 2 ++ src/libopensc/reader-pcsc.c | 49 +++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 2389d0c5..5cad5f54 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -201,6 +201,8 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\ #define PCSCv2_PART10_PROPERTY_sFirmwareID 8 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 #define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 +#define PCSCv2_PART10_PROPERTY_wIdVendor 11 +#define PCSCv2_PART10_PROPERTY_wIdProduct 12 /* structures used (but not defined) in PCSC Part 10: * "IFDs with Secure Pin Entry Capabilities" */ diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index b850db20..9ae16d0f 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -880,6 +880,46 @@ err: return max_data; } +static int part10_get_vendor_product(struct sc_reader *reader, + SCARDHANDLE card_handle, int *id_vendor, int *id_product) +{ + u8 rbuf[256]; + DWORD rcount = sizeof rbuf; + struct pcsc_private_data *priv; + /* 0 means no limitations */ + int this_vendor = -1, this_product = -1; + + if (!reader) + return SC_ERROR_INVALID_ARGUMENTS; + priv = GET_PRIV_DATA(reader); + if (!priv) + return SC_ERROR_INVALID_ARGUMENTS; + + 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!"); + return SC_ERROR_TRANSMIT_FAILED; + } + + this_vendor = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_wIdVendor); + this_product = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_wIdProduct); + } + + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "id_vendor=%04x id_product=%04x", this_vendor, this_product); + + if (id_vendor) + *id_vendor = this_vendor; + if (id_product) + *id_product = this_product; + + return SC_SUCCESS; +} + 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; @@ -1004,10 +1044,15 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) } } - /* 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); + /* Set reader max_send_size and max_recv_size based on + * detected max_data */ + reader->max_send_size = part10_detect_max_data(reader, + card_handle); reader->max_recv_size = reader->max_send_size; + + /* debug the product and vendor ID of the reader */ + part10_get_vendor_product(reader, card_handle, NULL, NULL); } } From b2508b6c5956bf7f13f619303c20f362614528da Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 2 Sep 2015 10:49:12 +0200 Subject: [PATCH 10/20] removed workaround for HP USB Smart Card Keyboard Has been fixed by the CCID driver https://lists.alioth.debian.org/pipermail/pcsclite-cvs-commit/2011-March/005218.html --- src/libopensc/reader-pcsc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 9ae16d0f..de137959 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -929,7 +929,6 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) PCSC_TLV_STRUCTURE *pcsc_tlv; LONG rv; const char *log_disabled = "but it's disabled in configuration file"; - const char *broken_readers[] = {"HP USB Smart Card Keyboard"}; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -997,14 +996,6 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) } } - /* Ignore advertised pinpad capability on readers known to be broken. Trac #340 */ - for (i = 0; i < sizeof(broken_readers)/sizeof(broken_readers[0]); i++) { - if (strstr(reader->name, broken_readers[i]) && (reader->capabilities & SC_READER_CAP_PIN_PAD)) { - sc_log(ctx, "%s has a broken pinpad, ignoring", reader->name); - reader->capabilities &= ~SC_READER_CAP_PIN_PAD; - } - } - /* Detect display */ if (priv->pin_properties_ioctl) { rcount = sizeof(rbuf); From a52b2928cd4f815e53d9fd388851672e0886c8d4 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 3 Sep 2015 05:41:20 +0200 Subject: [PATCH 11/20] retry on error with hdiutil --- MacOSX/build-package.in | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 86a2a729..142033b4 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -88,4 +88,12 @@ pkgbuild --nopayload --identifier org.opensc-project.mac.uninstall --scripts Mac # Create .dmg rm -f OpenSC-@PACKAGE_VERSION@.dmg TIMESTAMP=$(date +%Y.%m.%d) -hdiutil create -srcfolder Uninstall_OpenSC.pkg -srcfolder OpenSC-@PACKAGE_VERSION@.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.9+ (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@.dmg +i=0 +while ! hdiutil create -srcfolder Uninstall_OpenSC.pkg -srcfolder OpenSC-@PACKAGE_VERSION@.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.9+ (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@.dmg +do + i=$[$i+1] + if [ $i -gt 2 ] + then + exit 1 + fi +done From 68796edf36c610baef90755863f01ae7aab6a223 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Thu, 3 Sep 2015 15:09:23 +0200 Subject: [PATCH 12/20] add '--raw' option to output 8 bit data instead of its hex representation --- src/tools/pkcs15-tool.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index f7cc6469..43e80b46 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -50,6 +50,7 @@ static char * opt_auth_id = NULL; static char * opt_reader = NULL; static char * opt_cert = NULL; static char * opt_data = NULL; +static int opt_raw = 0; static char * opt_pubkey = NULL; static char * opt_outfile = NULL; static char * opt_bind_to_aid = NULL; @@ -82,6 +83,7 @@ enum { OPT_LIST_APPLICATIONS, OPT_LIST_SKEYS, OPT_NO_PROMPT, + OPT_RAW, }; #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) @@ -94,6 +96,7 @@ static const struct option options[] = { { "read-certificate", required_argument, NULL, 'r' }, { "list-certificates", no_argument, NULL, 'c' }, { "read-data-object", required_argument, NULL, 'R' }, + { "raw", no_argument, NULL, OPT_RAW }, { "list-data-objects", no_argument, NULL, 'C' }, { "list-pins", no_argument, NULL, OPT_LIST_PINS }, { "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS }, @@ -130,6 +133,7 @@ static const char *option_help[] = { "Reads certificate with ID ", "Lists certificates", "Reads data object with OID, applicationName or label ", + "Outputs raw 8 bit data to stdout", "Lists data objects", "Lists PIN codes", "Lists secret keys", @@ -346,18 +350,28 @@ print_data_object(const char *kind, const u8*data, size_t data_len) } for (i=0; i < data_len; i++) fprintf(outf, "%c", data[i]); - printf("Dumping (%lu bytes) to file <%s>: <", - (unsigned long) data_len, opt_outfile); - for (i=0; i < data_len; i++) - printf(" %02X", data[i]); - printf(" >\n"); + if (opt_raw) { + for (i=0; i < data_len; i++) + printf("%c", data[i]); + } else { + printf("Dumping (%lu bytes) to file <%s>: <", + (unsigned long) data_len, opt_outfile); + for (i=0; i < data_len; i++) + printf(" %02X", data[i]); + printf(" >\n"); + } fclose(outf); } else { - printf("%s (%lu bytes): <", - kind, (unsigned long) data_len); - for (i=0; i < data_len; i++) - printf(" %02X", data[i]); - printf(" >\n"); + if (opt_raw) { + for (i=0; i < data_len; i++) + printf("%c", data[i]); + } else { + printf("%s (%lu bytes): <", + kind, (unsigned long) data_len); + for (i=0; i < data_len; i++) + printf(" %02X", data[i]); + printf(" >\n"); + } } return 0; } @@ -1931,6 +1945,9 @@ int main(int argc, char * const argv[]) do_read_data_object = 1; action_count++; break; + case OPT_RAW: + opt_raw = 1; + break; case 'C': do_list_data_objects = 1; action_count++; From 69f92faec5009e7c3296993668ddd659993038e4 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 3 Sep 2015 16:02:26 +0200 Subject: [PATCH 13/20] added appveyor configuration --- appveyor.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..b4d4c4bd --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,7 @@ +before_build: + - cd "C:\Program Files\Microsoft Visual Studio 10.0\VC\" + - call vcvarsall.bat x86 + +build_script: + - cd %APPVEYOR_BUILD_FOLDER%\win32 + - nmake -f Makefile.mak From 72e25db360fd4d3dadd3c8bd5e40d7da2a4c967a Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Thu, 3 Sep 2015 21:18:40 +0200 Subject: [PATCH 14/20] sc-hsm: Add status info support for SmartCard-HSM V2.0 --- src/libopensc/card-sc-hsm.c | 2 +- src/libopensc/card-sc-hsm.h | 3 ++ src/tools/sc-hsm-tool.c | 74 ++++++++++++++++++++++++++++++------- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 0613d49b..917eb171 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -867,7 +867,7 @@ static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *pa memset(&ip, 0, sizeof(ip)); ip.dkek_shares = -1; ip.options[0] = 0x00; - ip.options[0] = 0x01; + ip.options[1] = 0x01; r = sc_hsm_encode_sopin(params->so_pin, ip.init_code); LOG_TEST_RET(ctx, r, "SO PIN wrong format"); diff --git a/src/libopensc/card-sc-hsm.h b/src/libopensc/card-sc-hsm.h index 12d18673..325f73fd 100644 --- a/src/libopensc/card-sc-hsm.h +++ b/src/libopensc/card-sc-hsm.h @@ -50,6 +50,9 @@ #define ID_USER_PIN 0x81 /* User PIN identifier */ #define ID_SO_PIN 0x88 /* Security officer PIN identifier */ +#define INIT_RRC_ENABLED 0x01 /* Bit 1 of initialization options */ +#define INIT_TRANSPORT_PIN 0x02 /* Bit 2 of initialization options */ + /* Information the driver maintains between calls */ typedef struct sc_hsm_private_data { const sc_security_env_t *env; diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index 22680c33..8fa26c18 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -461,27 +461,75 @@ static void print_info(sc_card_t *card, sc_file_t *file) struct sc_pin_cmd_data data; sc_cardctl_sc_hsm_dkek_t dkekinfo; - u8 major, minor; + u8 major, minor, opt; major = file->prop_attr[file->prop_attr_len - 2]; minor = file->prop_attr[file->prop_attr_len - 1]; printf("Version : %d.%d\n", (int)major, (int)minor); - /* Try to update PIN info from card */ - memset(&data, 0, sizeof(data)); - data.cmd = SC_PIN_CMD_GET_INFO; - data.pin_type = SC_AC_CHV; - data.pin_reference = ID_USER_PIN; + if (file->prop_attr_len > 2) { /* Version >= 2.0 */ + opt = file->prop_attr[file->prop_attr_len - 4]; + if (opt != 0) { + printf("Config options :\n"); + if (opt & INIT_RRC_ENABLED) { + printf(" User PIN reset with SO-PIN enabled\n"); + } + if (opt & INIT_TRANSPORT_PIN) { + printf(" Transport-PIN mode enabled\n"); + } + } - r = sc_pin_cmd(card, &data, &tries_left); + /* Try to update SO-PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_SO_PIN; - if (r == SC_ERROR_REF_DATA_NOT_USABLE) { - printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); - } else { - if (tries_left == 0) { - printf("User PIN locked\n"); + r = sc_pin_cmd(card, &data, &tries_left); + if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) { + printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); } else { - printf("User PIN tries left : %d\n", tries_left); + if (tries_left == 0) { + printf("SO-PIN locked\n"); + } else { + printf("SO-PIN tries left : %d\n", tries_left); + } + /* Try to update PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_USER_PIN; + + r = sc_pin_cmd(card, &data, &tries_left); + if (r == SC_ERROR_CARD_CMD_FAILED) { + printf("Public key authentication active.\n"); + } else if (r == SC_ERROR_REF_DATA_NOT_USABLE) { + printf("Transport-PIN active. Please change to user selected PIN first.\n"); + } else { + if (tries_left == 0) { + printf("User PIN locked\n"); + } else { + printf("User PIN tries left : %d\n", tries_left); + } + } + } + } else { /* Version < 2.0 */ + /* Try to update PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_USER_PIN; + + r = sc_pin_cmd(card, &data, &tries_left); + + if (r == SC_ERROR_REF_DATA_NOT_USABLE) { + printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); + } else { + if (tries_left == 0) { + printf("User PIN locked\n"); + } else { + printf("User PIN tries left : %d\n", tries_left); + } } } From 09308033004a54e16eff153f6b28d7681aa5df28 Mon Sep 17 00:00:00 2001 From: Ludovic Rousseau Date: Fri, 4 Sep 2015 09:01:20 +0200 Subject: [PATCH 15/20] add AppVeyor build status For now it uses my own appveyor account. Maybe it is possible to use an OpenSC team appveyor account or something like that instead. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 714ad043..69836176 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,5 @@ Jenkins CI: Travis CI: [![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) +AppVeyor CI: +[![Build status](https://ci.appveyor.com/api/projects/status/94wjbxyfb0u3cvg9?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/opensc) From f44e229865ec063d103feeee8de32d64b1c1d659 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Fri, 4 Sep 2015 13:04:24 +0200 Subject: [PATCH 16/20] update help message to clarify that --raw only affects stdout behavior --- src/tools/pkcs15-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 43e80b46..92d51c9c 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -133,7 +133,7 @@ static const char *option_help[] = { "Reads certificate with ID ", "Lists certificates", "Reads data object with OID, applicationName or label ", - "Outputs raw 8 bit data to stdout", + "Outputs raw 8 bit data to stdout. File output will not be affected by this, it always uses raw mode.", "Lists data objects", "Lists PIN codes", "Lists secret keys", From e9b1b2e9e8cf540f3cb4d5f7e4447a71e7bac603 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Fri, 4 Sep 2015 13:09:54 +0200 Subject: [PATCH 17/20] update pkcs15 documentation to describe --raw option --- doc/tools/pkcs15-tool.1.xml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml index 82ad7b91..79b0e506 100644 --- a/doc/tools/pkcs15-tool.1.xml +++ b/doc/tools/pkcs15-tool.1.xml @@ -154,6 +154,18 @@ If this option is not given, keys will be printed to standard output. + + + + + Changes how prints the content + to standard output. By default, when is not given, it will + print the content in hex notation. If is set, it will print + the binary data directly. This does not affect the output that is written to the + file specified by the option. Data written to a file will + always be in raw binary. + + cert, @@ -168,7 +180,12 @@ data Reads data object with OID, applicationName or label. - + The content is printed to standard output in hex notation, unless + the option is given. + If an output file is given with the option, + the content is additionally written to the file. + Output to the file is always written in raw binary mode, the + only affects standard output behavior. From 6e3f94b3c9c694c872a364919604a6e3ef56ecb7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 10 Sep 2015 08:31:30 +0200 Subject: [PATCH 18/20] fixed bad string comparison fixes #547 --- src/libopensc/pkcs15.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index ba9d6125..f7c49ef2 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -424,8 +424,9 @@ fix_starcos_pkcs15_card(struct sc_pkcs15_card *p15card) if (strcmp(p15card->card->driver->short_name,"cardos") == 0) { /* D-Trust cards (D-TRUST, D-SIGN) */ - if (strstr(p15card->tokeninfo->label,"D-TRUST") != NULL - || strstr(p15card->tokeninfo->label,"D-SIGN") != NULL) { + if (p15card->tokeninfo->label + && (strstr(p15card->tokeninfo->label,"D-TRUST") != NULL + || strstr(p15card->tokeninfo->label,"D-SIGN") != NULL)) { /* D-TRUST Card 2.0 2cc (standard cards, which always add * SHA1 prefix itself */ From b40e2226b2009f8162c85aec03100fa8a92f87d2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 4 Sep 2015 00:01:44 +0200 Subject: [PATCH 19/20] AppVeyor: build with cccl wrapper for windows currently every job finally fails, but at least we can see most compilation errors --- appveyor.yml | 74 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b4d4c4bd..cb227013 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,71 @@ -before_build: - - cd "C:\Program Files\Microsoft Visual Studio 10.0\VC\" - - call vcvarsall.bat x86 +platform: + - x86 + - x64 + +environment: + matrix: + - VSVER: 14 + - VSVER: 12 + - VSVER: 10 + +matrix: + allow_failures: + # not included in AppVeyor right now + - platform: x64 + VSVER: 10 + # does not currently work + - VSVER: 14 + - VSVER: 12 + - VSVER: 10 + +install: + - date /T & time /T + - set PATH=C:\cygwin\bin;%PATH% + - ps: >- + If(!(Test-Path -Path "C:\cccl-1.0" )) { + git clone -q --depth=1 git://github.com/swig/cccl.git "C:\cccl-1.0" + } + - bash -c "cp C:/cccl-1.0/cccl /usr/bin" + - ps: >- + If ($env:Platform -Match "x86") { + $env:JAVA_HOME="C:/Program Files (x86)/Java/jdk1.8.0" + $env:VCVARS_PLATFORM="x86" + $env:ENV_PLATFORM="x86" + $env:OPENSSL="https://slproweb.com/download/Win32OpenSSL-1_0_2d.exe" + $env:NMAKE_FLAGS="" + } Else { + $env:JAVA_HOME="C:/Program Files/Java/jdk1.8.0" + $env:VCVARS_PLATFORM="amd64" + $env:ENV_PLATFORM="x64" + $env:OPENSSL="https://slproweb.com/download/Win64OpenSSL-1_0_2d.exe" + $env:NMAKE_FLAGS="BUILD_ON=WIN64 BUILD_FOR=WIN64" + } + - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) + - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" + - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% + - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /%ENV_PLATFORM% /Release + - appveyor DownloadFile %OPENSSL% -FileName C:\WinOpenSSL.exe + - C:\WinOpenSSL.exe /SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART /DIR="C:\OpenSSL" + - appveyor DownloadFile "http://prdownloads.sourceforge.net/libpng/zlib128-dll.zip" + - 7z x zlib128-dll.zip -oC:\zlib-1.2.8-dll + - bash -c "which cl.exe" + - bash -c "cl.exe /? 2>&1 | head -n 2" + - bash -c "which csc.exe" + - bash -c "csc.exe /? | head -n 2" + - bash -c "which cccl" + - bash -c "cccl --version" + - uname -a build_script: - - cd %APPVEYOR_BUILD_FOLDER%\win32 - - nmake -f Makefile.mak + - set CCCL_OPTIONS=--cccl-muffle /W3 /D_CRT_SECURE_NO_DEPRECATE /Dsnprintf=_snprintf + - set CC=cccl + - set CXX=cccl + - set LD=cccl + - bash -c "exec 0> /tmp/oscout 2>&1 && ./configure >> /tmp/oscout 2>&1" + #- nmake /f Makefile.mak %NMAKE_FLAGS% From 819a6686c91548cba4dbc1bfc9fb422c66d9a5ae Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 9 Sep 2015 14:51:09 +0200 Subject: [PATCH 20/20] use _WIN32 instead of WIN32 --- src/common/libscdl.c | 2 +- src/libopensc/internal-winscard.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/libscdl.c b/src/common/libscdl.c index a78f9e2f..bc1d6b87 100644 --- a/src/common/libscdl.c +++ b/src/common/libscdl.c @@ -24,7 +24,7 @@ #include "libscdl.h" -#ifdef WIN32 +#ifdef _WIN32 #include void *sc_dlopen(const char *filename) { diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 2389d0c5..d2bb56e8 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -21,7 +21,7 @@ typedef unsigned __int8 uint8_t; #include #endif // allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW -#ifdef WIN32 +#ifdef _WIN32 #ifdef UNICODE #define SCARD_READERSTATE SCARD_READERSTATEA #undef SCardGetStatusChange