On Mon, 2011-02-07 at 11:32 -0600, Douglas E. Engert wrote: > > On 2/4/2011 2:20 AM, Martin Paljak wrote: > > > I think Douglas is incrementally working on the existing codebase. Why the > > cardmod > > driver was squeezed into reader-pcsc.c the way it is in the first place is > beyond > > me, as Francois noted, I "was not very hot about it" [1]. > > > > Yes, I am trying to work with the current code base. The missing piece is > passing > in the two handles from the cardmod.c to the reader-pcsc.c cardmod code. > The use of the use_reader and sc_ctx_use_reader can do this.
Have a look at the attached patch. 1. It uses the init() function of reader-drivers to pass in additional arguments. 2. It adds two fields to sc_context_param_t to let the caller of sc_context_create() provide its own custom driver. How that is to be used is shown in the diff of src/cardmod/cardmod.c Additionally a stripped down reader-pcsc (renamed to reader-cardmod) is attached. It works well with a modified version of opensc-pkcs11.so and should work in the same way for cardmod. Integration into the build system is still required and possibly some debugging. Regards Andre
Index: src/libopensc/reader-pcsc.c =================================================================== --- src/libopensc/reader-pcsc.c (revision 5188) +++ src/libopensc/reader-pcsc.c (working copy) @@ -612,7 +612,7 @@ 0, 0, NULL }; -static int pcsc_init(sc_context_t *ctx) +static int pcsc_init(void *init_data, sc_context_t *ctx) { struct pcsc_global_private_data *gpriv; scconf_block *conf_block = NULL; @@ -1580,7 +1580,7 @@ 0, 0, NULL }; -static int cardmod_init(sc_context_t *ctx) +static int cardmod_init(void *init_data, sc_context_t *ctx) { struct pcsc_global_private_data *gpriv; scconf_block *conf_block = NULL; Index: src/libopensc/ctx.c =================================================================== --- src/libopensc/ctx.c (revision 5188) +++ src/libopensc/ctx.c (working copy) @@ -105,6 +105,7 @@ /* The default driver should be last, as it handles all the * unrecognized cards. */ { "default", (void *(*)(void)) sc_get_default_driver }, + { "iso7816", (void *(*)(void)) sc_get_iso7816_driver }, { NULL, NULL } }; @@ -648,21 +649,20 @@ return SC_ERROR_OUT_OF_MEMORY; } + if (parm->reader_drv != NULL) { + ctx->reader_driver = parm->reader_drv; + } else { #ifdef ENABLE_PCSC ctx->reader_driver = sc_get_pcsc_driver(); - #ifdef ENABLE_CARDMOD - if(strcmp(ctx->app_name, "cardmod") == 0) { - ctx->reader_driver = sc_get_cardmod_driver(); - } - #endif #elif ENABLE_CTAPI ctx->reader_driver = sc_get_ctapi_driver(); #elif ENABLE_OPENCT ctx->reader_driver = sc_get_openct_driver(); #endif + } load_reader_driver_options(ctx); - ctx->reader_driver->ops->init(ctx); + ctx->reader_driver->ops->init(parm->reader_drv_init_data, ctx); load_card_drivers(ctx, &opts); load_card_atrs(ctx); Index: src/libopensc/reader-ctapi.c =================================================================== --- src/libopensc/reader-ctapi.c (revision 5188) +++ src/libopensc/reader-ctapi.c (working copy) @@ -499,7 +499,7 @@ return -1; } -static int ctapi_init(sc_context_t *ctx) +static int ctapi_init(void *init_data, sc_context_t *ctx) { int i; struct ctapi_global_private_data *gpriv; Index: src/libopensc/reader-openct.c =================================================================== --- src/libopensc/reader-openct.c (revision 5188) +++ src/libopensc/reader-openct.c (working copy) @@ -64,7 +64,7 @@ * is loaded */ static int -openct_reader_init(sc_context_t *ctx) +openct_reader_init(void *init_data, sc_context_t *ctx) { unsigned int i,max_virtual; scconf_block *conf_block; Index: src/libopensc/opensc.h =================================================================== --- src/libopensc/opensc.h (revision 5188) +++ src/libopensc/opensc.h (working copy) @@ -250,7 +250,7 @@ #define SC_PROTO_RAW 0x00001000 #define SC_PROTO_ANY 0xFFFFFFFF -struct sc_reader_driver { +typedef struct sc_reader_driver { const char *name; const char *short_name; struct sc_reader_operations *ops; @@ -258,7 +258,7 @@ size_t max_send_size; /* Max Lc supported by the reader layer */ size_t max_recv_size; /* Mac Le supported by the reader layer */ void *dll; -}; +} sc_reader_driver_t; /* reader flags */ #define SC_READER_CARD_PRESENT 0x00000001 @@ -359,7 +359,7 @@ struct sc_reader_operations { /* Called during sc_establish_context(), when the driver * is loaded */ - int (*init)(struct sc_context *ctx); + int (*init)(void *init_data, struct sc_context *ctx); /* Called when the driver is being unloaded. finish() has to * release any resources. */ int (*finish)(struct sc_context *ctx); @@ -692,6 +692,10 @@ unsigned long flags; /** mutex functions to use (optional) */ sc_thread_context_t *thread_ctx; + /** custom reader driver or NULL for default driver **/ + sc_reader_driver_t *reader_drv; + /** initial data **/ + void *reader_drv_init_data; } sc_context_param_t; /** * Creates a new sc_context_t object. Index: src/cardmod/cardmod.c =================================================================== --- src/cardmod/cardmod.c (revision 5188) +++ src/cardmod/cardmod.c (working copy) @@ -1412,6 +1412,8 @@ memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 1; ctx_param.app_name = "cardmod"; + ctx_param.reader_drv = get_reader_driver(); + ctx_param.reader_drv_init_data = /* pointer to struct {SCARDCONTEXT hSCardCtx, SCARDHANDLE hSCard} */ if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenSC Project\\Opensc", 0, NULL, \ REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
/* * reader-pcsc.c: Reader driver for PC/SC interface * * Copyright (C) 2002 Juha Yrjölä <juha.yrj...@iki.fi> * Copyright (C) 2009,2010 Martin Paljak <mar...@paljak.pri.ee> * * 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 "config.h" #include <assert.h> #include <stdlib.h> #include <string.h> #include "../libopensc/internal.h" #include "../libopensc/internal-winscard.h" #include "reader-cardmod.h" /* Logging */ #define PCSC_TRACE(reader, desc, rv) do { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s:" desc ": 0x%08lx\n", reader->name, rv); } while (0) #define PCSC_LOG(ctx, desc, rv) do { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, desc ": 0x%08lx\n", rv); } while (0) struct pcsc_private_data { SCARDCONTEXT hSCardCtx; SCARDHANDLE hSCard; DWORD dwProtocol; }; static unsigned int pcsc_proto_to_opensc(DWORD proto) { switch (proto) { case SCARD_PROTOCOL_T0: return SC_PROTO_T0; case SCARD_PROTOCOL_T1: return SC_PROTO_T1; case SCARD_PROTOCOL_RAW: return SC_PROTO_RAW; default: return 0; } } static int pcsc_internal_transmit(sc_reader_t *reader, const u8 *sendbuf, size_t sendsize, u8 *recvbuf, size_t *recvsize, unsigned long control) { struct pcsc_private_data *priv = (struct pcsc_private_data *) reader->ctx->reader_drv_data; SCARD_IO_REQUEST sSendPci, sRecvPci; DWORD dwSendLength, dwRecvLength; LONG rv; SCARDHANDLE card; SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); card = priv->hSCard; sSendPci.dwProtocol = priv->dwProtocol; sSendPci.cbPciLength = sizeof(sSendPci); sRecvPci.dwProtocol = priv->dwProtocol; sRecvPci.cbPciLength = sizeof(sRecvPci); dwSendLength = sendsize; dwRecvLength = *recvsize; if (!control) { rv = SCardTransmit(card, &sSendPci, sendbuf, dwSendLength, &sRecvPci, recvbuf, &dwRecvLength); } else { rv = SCardControl(card, (DWORD) control, sendbuf, dwSendLength, recvbuf, dwRecvLength, &dwRecvLength); } if (rv != SCARD_S_SUCCESS) { PCSC_TRACE(reader, "SCardTransmit/Control failed", rv); switch (rv) { case SCARD_W_REMOVED_CARD: return SC_ERROR_CARD_REMOVED; default: return SC_ERROR_TRANSMIT_FAILED; } } if (!control && dwRecvLength < 2) return SC_ERROR_UNKNOWN_DATA_RECEIVED; *recvsize = dwRecvLength; return SC_SUCCESS; } static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu) { size_t ssize, rsize, rbuflen = 0; u8 *sbuf = NULL, *rbuf = NULL; int r; struct pcsc_private_data *priv = (struct pcsc_private_data *) reader->ctx->reader_drv_data; /* we always use a at least 258 byte size big return buffer * to mimic the behaviour of the old implementation (some readers * seems to require a larger than necessary return buffer). * The buffer for the returned data needs to be at least 2 bytes * larger than the expected data length to store SW1 and SW2. */ rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2; rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } /* encode and log the APDU */ r = sc_apdu_get_octets(reader->ctx, apdu, &sbuf, &ssize, pcsc_proto_to_opensc(priv->dwProtocol)); if (r != SC_SUCCESS) goto out; if (reader->name) sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "reader '%s'", reader->name); sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, sbuf, ssize, 1); r = pcsc_internal_transmit(reader, sbuf, ssize, rbuf, &rsize, apdu->control); if (r < 0) { /* unable to transmit ... most likely a reader problem */ sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to transmit"); goto out; } sc_apdu_log(reader->ctx, SC_LOG_DEBUG_NORMAL, rbuf, rsize, 0); /* set response */ r = sc_apdu_set_resp(reader->ctx, apdu, rbuf, rsize); out: if (sbuf != NULL) { sc_mem_clear(sbuf, ssize); free(sbuf); } if (rbuf != NULL) { sc_mem_clear(rbuf, rbuflen); free(rbuf); } return r; } static int pcsc_init(void *init_data, sc_context_t *ctx) { struct pcsc_private_data *priv; sc_reader_t *reader; DWORD atr_len = SC_MAX_ATR_SIZE; DWORD name_len; DWORD dwState; size_t i; int r; if (init_data == NULL || ctx == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } if (ctx->reader_drv_data != NULL) { return SC_ERROR_INVALID_DATA; /* Already initialised */ } ctx->reader_drv_data = calloc(1, sizeof(struct pcsc_private_data)); if (ctx->reader_drv_data == NULL) { return SC_ERROR_OUT_OF_MEMORY; } priv = ctx->reader_drv_data; priv->hSCardCtx = ((pcsc_ctx_t *) init_data)->hSCardCtx; priv->hSCard = ((pcsc_ctx_t *) init_data)->hSCard; reader = calloc(1, sizeof(sc_reader_t)); if (reader == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto error; } name_len = 127; reader->name = malloc(sizeof(char) * (name_len + 1)); if (reader->name == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto error; } r = SCardStatus(priv->hSCard, reader->name, &name_len, &dwState, &priv->dwProtocol, reader->atr.value, &atr_len); if (r != SCARD_S_SUCCESS) { printf("%s\n", pcsc_stringify_error(r)); r = SC_ERROR_READER; goto error; } reader->name[name_len] = 0; reader->atr.len = atr_len; printf("Current Reader Name : %s\n", reader->name); printf("Current Reader State : 0x%lx\n", dwState); printf("Current Reader Protocol : T%ld\n", priv->dwProtocol - 1); printf("Current Reader ATR Size : %u\n", reader->atr.len); printf("Current Reader ATR Value : "); for (i = 0; i < reader->atr.len; i++) { printf("%02X ", reader->atr.value[i]); } printf("\n"); reader->flags = SC_READER_CARD_PRESENT; reader->driver = ctx->reader_driver; reader->ops = reader->driver->ops; r = _sc_add_reader(ctx, reader); if (r != SC_SUCCESS) { goto error; } return SC_SUCCESS; error: if (reader != NULL) { if (reader->name != NULL) free(reader->name); free(reader); } free(ctx->reader_drv_data); ctx->reader_drv_data = NULL; return r; } static int pcsc_finish(sc_context_t *ctx) { if (ctx->reader_drv_data != NULL) { free(ctx->reader_drv_data); ctx->reader_drv_data = NULL; } return SC_SUCCESS; } static int pcsc_detect_card_presence(sc_reader_t *reader) { return SC_READER_CARD_PRESENT; } static int pcsc_connect(sc_reader_t *reader) { return SC_SUCCESS; } static int pcsc_disconnect(sc_reader_t * reader) { return SC_SUCCESS; } struct sc_reader_driver * get_reader_driver(void) { struct sc_reader_driver *pcsc_drv; pcsc_drv = calloc(1, sizeof(struct sc_reader_driver)); if (pcsc_drv == NULL) { return NULL; } pcsc_drv->ops = calloc(1, sizeof(struct sc_reader_operations)); if (pcsc_drv->ops == NULL) { free(pcsc_drv); return NULL; } pcsc_drv->name = "cardmod"; pcsc_drv->short_name = "cardmod"; pcsc_drv->ops->init = pcsc_init; pcsc_drv->ops->finish = pcsc_finish; pcsc_drv->ops->detect_card_presence = pcsc_detect_card_presence; pcsc_drv->ops->connect = pcsc_connect; pcsc_drv->ops->disconnect = pcsc_disconnect; pcsc_drv->ops->transmit = pcsc_transmit; return pcsc_drv; }
typedef struct pcsc_ctx { SCARDCONTEXT hSCardCtx; SCARDHANDLE hSCard; } pcsc_ctx_t; struct sc_reader_driver * get_reader_driver(void);
_______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel