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ä <[email protected]>
+ * Copyright (C) 2007 Georges Bart <[email protected]>
+ *
+ * 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
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel