Am Donnerstag 22 Mai 2008 15:42:19 schrieb Georges Bart: > > I bought a card from gemalto (Classic TPC IM) and I've got some problem > > to interact with it and opensc. > > I think your card is using the GemSafe v2 applet with a PKCS#15 mapping. > > I sent a patch last year to try to support this card in OpenSC. > http://www.opensc-project.org/pipermail/opensc-user/2007-August/001958.html > > I attach a new version of the patch against trunk as of today and with > corrections suggested by Andreas.
oops, this patch was ignored for some reason. can everyone please review the patch? unless some issue is found, I think we should apply it. I'm not 100% sure why the new function sc_pkcs15_read_file_key_ref is needed, or if we can handle that some other way. but it's not a big deal if we mark it "gemsave V2 workaround" and keep that change. Regards, Andreas
Index: src/libopensc/ctx.c =================================================================== --- src/libopensc/ctx.c (révision 3516) +++ src/libopensc/ctx.c (copie de travail) @@ -60,6 +60,7 @@ static const struct _sc_driver_entry int { "gpk", (void *(*)(void)) sc_get_gpk_driver }, #endif { "gemsafeV1", (void *(*)(void)) sc_get_gemsafeV1_driver }, + { "gemsafeV2", (void *(*)(void)) sc_get_gemsafeV2_driver }, { "miocos", (void *(*)(void)) sc_get_miocos_driver }, { "mcrd", (void *(*)(void)) sc_get_mcrd_driver }, { "asepcos", (void *(*)(void)) sc_get_asepcos_driver }, Index: src/libopensc/pkcs15-pubkey.c =================================================================== --- src/libopensc/pkcs15-pubkey.c (révision 3516) +++ src/libopensc/pkcs15-pubkey.c (copie de travail) @@ -399,7 +399,11 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_c } info = (const struct sc_pkcs15_pubkey_info *) obj->data; - r = sc_pkcs15_read_file(p15card, &info->path, &data, &len, NULL); + if (info->path.len) + r = sc_pkcs15_read_file(p15card, &info->path, &data, &len, NULL); + else + r = sc_pkcs15_read_file_key_ref(p15card, info->key_reference, &data, &len); + if (r < 0) { sc_error(p15card->card->ctx, "Failed to read public key file."); return r; Index: src/libopensc/pkcs15.c =================================================================== --- src/libopensc/pkcs15.c (révision 3516) +++ src/libopensc/pkcs15.c (copie de travail) @@ -867,8 +867,14 @@ __sc_pkcs15_search_objects(sc_pkcs15_car /* Enumerate the DF's, so p15card->obj_list is * populated. */ r = sc_pkcs15_parse_df(p15card, df); - SC_TEST_RET(p15card->card->ctx, r, "DF parsing failed"); - df->enumerated = 1; + /* The DF is here but we can't read it yet */ + if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) + sc_do_log(p15card->card->ctx, SC_LOG_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, "DF parsing failed"); + else if (r < 0) + sc_do_log(p15card->card->ctx, SC_LOG_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, "%s: %s\n", "DF parsing failed", sc_strerror(r)); \ + else + /* r == SC_SUCCESS */ + df->enumerated = 1; } /* And now loop over all objects */ @@ -1608,6 +1614,60 @@ int sc_pkcs15_parse_unusedspace(const u8 return 0; } +int sc_pkcs15_read_file_key_ref(struct sc_pkcs15_card *p15card, + int key_reference, + u8 **buf, size_t *buflen) +{ + u8 *data = NULL; + size_t len = 0; + int r; + + assert(p15card != NULL && buf != NULL); + + if (p15card->card->ctx->debug >= 1) + sc_debug(p15card->card->ctx, "called, key ref=%d\n", key_reference); + + r = -1; /* file state: not in cache */ + /* if (p15card->opts.use_cache) { + r = sc_pkcs15_read_cached_file(p15card, path, &data, &len); + } */ + if (r) { + unsigned char buffer[512]; + + r = sc_get_data(p15card->card, key_reference, buffer, sizeof(buffer)); + if (r < 0) { + free(data); + goto fail_unlock; + } + + len = r; + + data = (u8 *) malloc(len); + if (data == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + goto fail_unlock; + } + data[0] = 0x30; + data[1] = 0x82; + data[2] = 0x00; + data[3] = 0x8B; + data[4] = 0x02; + data[5] = 0x81; + data[6] = 0x81; + data[7] = 0x00; + memcpy(data+8, buffer+14, len-14); + data[0x88] = 0x02; + data[0x89] = 0x04; + memmove(data+0x8A, data+0x8B, 4); + } + *buf = data; + *buflen = len; + return 0; + +fail_unlock: + return r; +} + int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, const sc_path_t *in_path, u8 **buf, size_t *buflen, Index: src/libopensc/pkcs15.h =================================================================== --- src/libopensc/pkcs15.h (révision 3516) +++ src/libopensc/pkcs15.h (copie de travail) @@ -605,6 +605,9 @@ int sc_pkcs15_parse_unusedspace(const u8 int sc_pkcs15_encode_unusedspace(sc_context_t *ctx, struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen); +int sc_pkcs15_read_file_key_ref(struct sc_pkcs15_card *p15card, + int key_reference, + u8 **buf, size_t *buflen); void sc_pkcs15_free_prkey_info(sc_pkcs15_prkey_info_t *key); void sc_pkcs15_free_pubkey_info(sc_pkcs15_pubkey_info_t *key); Index: src/libopensc/card-gemsafeV2.c =================================================================== --- src/libopensc/card-gemsafeV2.c (révision 0) +++ src/libopensc/card-gemsafeV2.c (révision 0) @@ -0,0 +1,137 @@ +/* + * card-gemsafeV2.c: Support for GemSafe Applet V2 PKCS#15 cards + * + * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrj...@iki.fi> + * Copyright (C) 2007 Georges Bart <georges.b...@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "internal.h" +#include <string.h> + +static struct sc_card_operations gemsafeV2_ops; +static struct sc_card_driver gemsafeV2_drv = { + "GemSafe V2 PKCS#15 card", + "GemSafeV2", + &gemsafeV2_ops, + NULL, 0, NULL +}; + +static int gemsafeV2_finish(sc_card_t *card) +{ + return 0; +} /* gemsafeV2_finish */ + +static const u8 atr[] = { 0x3B, 0xFD, 0x94, 0x00, 0x00, 0x81, 0x31, 0x20, 0x43, + 0x80, 0x31, 0x80, 0x65, 0xB0, 0x83, 0x02, 0x04, 0x7E, 0x83, 0x00, 0x90, + 0x00, 0xB6 }; + +static int gemsafeV2_match_card(sc_card_t *card) +{ + /* FIXME */ + return memcmp(atr, card -> atr, sizeof(atr)) == 0; /* correct ATR? */ +} /* gemsafeV2_match_card */ + +static const u8 gemsafeV2_aid[] = {0xa0, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, + 0x00, 0x01, 0x63, 0x42, 0x00}; + +static const u8 pin[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static int gemsafeV2_init(sc_card_t *card) +{ + int rv; + sc_apdu_t apdu; + unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE]; + + card->name = "GemSafe V2 PKCS#15 card"; + card->cla = 0x00; + card->drv_data = NULL; + + sc_debug(card -> ctx, "Test for GemSafe v2 card"); + + /* test if we have a gemsafeV2 app DF */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xa4, 0x04, 0x00); + apdu.lc = sizeof(gemsafeV2_aid); + apdu.le = 0; + apdu.data = gemsafeV2_aid; + apdu.datalen = sizeof(gemsafeV2_aid); + apdu.resplen = sizeof(apdu_resp); + apdu.resp = apdu_resp; + + rv = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); + if (!((apdu.sw1 == 0x90) && (apdu.sw2 == 0x00))) + return -1; + +#if 1 + sc_debug(card -> ctx, "Force a verify PIN"); + /* verify pin */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x81); + apdu.lc = sizeof(pin); + apdu.le = 0; + apdu.data = pin; + apdu.datalen = sizeof(pin); + apdu.resplen = sizeof(apdu_resp); + apdu.resp = apdu_resp; + + rv = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, rv, "APDU transmit failed"); + if (!((apdu.sw1 == 0x90) && (apdu.sw2 == 0x00))) + return -1; +#endif + + return 0; +} /* gemsafeV2_init */ + +static int +gemsafeV2_get_data(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) +{ + sc_apdu_t apdu; + int r; + u8 get_data[] = { 0xB6, 0x03, 0x83, 0x01, 0xff, 0x7F, 0x49, 0x80 }; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xCB, 0x00, 0xFF); + apdu.lc = sizeof(get_data); + apdu.le = 256; + apdu.resp = buf; + apdu.resplen = buf_len; + + get_data[4] = tag; + apdu.data = get_data; + apdu.datalen = sizeof(get_data); + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, r, "Card returned error"); + + return apdu.resplen; +} /* gemsafeV2_get_data */ + +struct sc_card_driver * sc_get_gemsafeV2_driver(void) +{ + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + + gemsafeV2_ops = *iso_drv->ops; + gemsafeV2_ops.get_data = gemsafeV2_get_data; + gemsafeV2_ops.match_card = gemsafeV2_match_card; + gemsafeV2_ops.init = gemsafeV2_init; + gemsafeV2_ops.finish = gemsafeV2_finish; + + return &gemsafeV2_drv; +} /* sc_get_gemsafeV2_driver */ + Index: src/libopensc/dir.c =================================================================== --- src/libopensc/dir.c (révision 3516) +++ src/libopensc/dir.c (copie de travail) @@ -33,6 +33,7 @@ struct app_entry { static const struct app_entry apps[] = { { (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" }, { (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" }, + { (const u8 *) "\xE8\x28\xBD\x08\x0F\x01Gem P15", 13, "GemSafe v2" }, }; static const struct app_entry * find_app_entry(const u8 * aid, size_t aid_len) Index: src/libopensc/Makefile.am =================================================================== --- src/libopensc/Makefile.am (révision 3516) +++ src/libopensc/Makefile.am (copie de travail) @@ -38,6 +38,7 @@ libopensc_la_SOURCES = \ card-oberthur.c card-belpic.c card-atrust-acos.c \ card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \ card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c\ + card-gemsafeV2.c \ \ pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ Index: src/libopensc/opensc.h =================================================================== --- src/libopensc/opensc.h (révision 3516) +++ src/libopensc/opensc.h (copie de travail) @@ -1195,6 +1195,7 @@ extern sc_card_driver_t *sc_get_belpic_d extern sc_card_driver_t *sc_get_atrust_acos_driver(void); extern sc_card_driver_t *sc_get_incrypto34_driver(void); extern sc_card_driver_t *sc_get_piv_driver(void); +extern sc_card_driver_t *sc_get_gemsafeV2_driver(void); extern sc_card_driver_t *sc_get_muscle_driver(void); extern sc_card_driver_t *sc_get_acos5_driver(void); extern sc_card_driver_t *sc_get_asepcos_driver(void);
_______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel