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

Reply via email to