diff -Nru openct-0.6.7/src/ifd/Makefile.am openct-0.6.7-rfid/src/ifd/Makefile.am --- openct-0.6.7/src/ifd/Makefile.am 2006-04-21 08:37:58.000000000 +0200 +++ openct-0.6.7-rfid/src/ifd/Makefile.am 2006-05-27 19:32:21.000000000 +0200 @@ -20,7 +20,7 @@ ifd-wbeiuu.c \ \ proto-gbp.c proto-sync.c proto-t0.c proto-t1.c \ - proto-trans.c \ + proto-trans.c proto-escape.c \ \ sys-sunray.c sys-solaris.c sys-bsd.c sys-linux.c sys-null.c sys-osx.c \ \ diff -Nru openct-0.6.7/src/ifd/ifd-ccid.c openct-0.6.7-rfid/src/ifd/ifd-ccid.c --- openct-0.6.7/src/ifd/ifd-ccid.c 2006-04-24 21:52:03.000000000 +0200 +++ openct-0.6.7-rfid/src/ifd/ifd-ccid.c 2006-05-27 19:46:29.000000000 +0200 @@ -5,6 +5,9 @@ * * 2005-04-20: Harald Welte * Add support for PCMCIA based CCID Device (CardMan 4040) + * + * 2005-05-22: Harald Welte + * Add suport for OmniKey Cardman 5121 RFID extensions */ #include "internal.h" @@ -122,6 +125,7 @@ #define SUPPORT_T0 0x1 #define SUPPORT_T1 0x2 +#define SUPPORT_ESCAPE 0x80 #define SUPPORT_50V 1 #define SUPPORT_33V 2 @@ -740,6 +744,12 @@ st->reader_type = TYPE_TPDU; } + if (de.idVendor == 0x076b && de.idProduct == 0x5121) { + /* special handling of RFID part of OmniKey 5121 */ + reader->nslots++; /* one virtual slot for RFID escape */ + st->proto_support |= SUPPORT_ESCAPE; + } + return 0; } @@ -816,6 +826,13 @@ int any = 0; int i, j, bits, stat; + if (st->proto_support & SUPPORT_ESCAPE + && slot == reader->nslots-1) { + ifd_debug(1, "virtual escape slot, setting card present\n"); + *status = IFD_CARD_PRESENT; + return 0; + } + i = 1 + (slot / 4); j = 2 * (slot % 4); stat = 0; @@ -880,6 +897,8 @@ return 0; } +static int ccid_set_protocol(ifd_reader_t *reader, int s, int proto); + /* * Reset */ @@ -898,6 +917,13 @@ if (!(status & IFD_CARD_PRESENT)) return IFD_ERROR_NO_CARD; + if (st->proto_support & SUPPORT_ESCAPE + && slot == reader->nslots-1) { + ifd_debug(1, "slot: %d, setting atr to 0xff", slot); + *((char *)atr) = 0xff; + ccid_set_protocol(reader, slot, IFD_PROTOCOL_ESCAPE); + return 1; + } memset(ctlbuf, 0, 3); n = -1; @@ -940,6 +966,17 @@ ifd_atr_info_t atr_info; int r; + slot = &reader->slot[s]; + + /* If we support RFID escaping, we only allow ESCAPE protocol + * at the last (== virtual) slot */ + if ((st->proto_support & SUPPORT_ESCAPE) + && (proto != IFD_PROTOCOL_ESCAPE) + && (s == reader->nslots-1)) { + ct_error("reader doesn't support this protocol at this slot\n"); + return IFD_ERROR_NOT_SUPPORTED; + } + switch (proto) { case IFD_PROTOCOL_T0: if (!(st->proto_support & SUPPORT_T0)) { @@ -953,13 +990,36 @@ return IFD_ERROR_NOT_SUPPORTED; } break; + case IFD_PROTOCOL_ESCAPE: + /* virtual "escape" fallthrough protocol for stacking RFID + * protocol stack on top of openct */ + if (!(st->proto_support & SUPPORT_ESCAPE)) { + ct_error("reader does not support this protocol"); + return IFD_ERROR_NOT_SUPPORTED; + } + if (s != reader->nslots-1) { + ct_error("reader doesn't support this protocol at this slot"); + return IFD_ERROR_NOT_SUPPORTED; + } + p = ifd_protocol_new(IFD_PROTOCOL_ESCAPE,reader, slot->dad); + if (!p) { + ct_error("%s: internal error", reader->name); + return -1; + } + if (slot->proto) { + ifd_protocol_free(slot->proto); + slot->proto = NULL; + } + slot->proto = p; + st->icc_proto[s] = proto; + ifd_debug(1, "set protocol to ESCAPE\n"); + return 0; + break; default: ct_error("protocol unknown"); return IFD_ERROR_NOT_SUPPORTED; } - slot = &reader->slot[s]; - if (st->reader_type == TYPE_APDU) { p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT, reader, slot->dad); @@ -1103,6 +1163,27 @@ return 0; } +static int ccid_escape(ifd_reader_t *reader, int slot, void *sbuf, + size_t slen, void *rbuf, size_t rlen) +{ + unsigned char sendbuf[CCID_MAX_MSG_LEN]; + unsigned char recvbuf[CCID_MAX_MSG_LEN]; + int r; + + ifd_debug(1, "slot: %d, slen %d, rlen %d", slot, slen, rlen); + + r = ccid_prepare_cmd(reader, sendbuf, sizeof(sendbuf), slot, + CCID_CMD_ESCAPE, NULL, sbuf, slen); + if (r < 0) + return r; + + r = ccid_command(reader, &sendbuf[0], r, recvbuf, sizeof(recvbuf)); + if (r < 0) + return r; + + return ccid_extract_data(&recvbuf, r, rbuf, rlen); +} + static int ccid_transparent(ifd_reader_t * reader, int slot, const void *sbuf, size_t slen, void *rbuf, size_t rlen) @@ -1177,6 +1258,7 @@ ccid_driver.transparent = ccid_transparent; ccid_driver.send = ccid_send; ccid_driver.recv = ccid_recv; + ccid_driver.escape = ccid_escape; ifd_driver_register("ccid", &ccid_driver); } diff -Nru openct-0.6.7/src/ifd/init.c openct-0.6.7-rfid/src/ifd/init.c --- openct-0.6.7/src/ifd/init.c 2006-04-21 08:37:58.000000000 +0200 +++ openct-0.6.7-rfid/src/ifd/init.c 2006-05-27 19:32:21.000000000 +0200 @@ -54,6 +54,7 @@ ifd_protocol_register(&ifd_protocol_2wire); ifd_protocol_register(&ifd_protocol_3wire); ifd_protocol_register(&ifd_protocol_eurochip); + ifd_protocol_register(&ifd_protocol_esc); if (ifd_conf_get_integer("debug", &ival) >= 0 && ival > ct_config.debug) ct_config.debug = ival; diff -Nru openct-0.6.7/src/ifd/internal.h openct-0.6.7-rfid/src/ifd/internal.h --- openct-0.6.7/src/ifd/internal.h 2006-04-21 08:37:58.000000000 +0200 +++ openct-0.6.7-rfid/src/ifd/internal.h 2006-05-27 19:32:21.000000000 +0200 @@ -118,6 +118,7 @@ extern struct ifd_protocol_ops ifd_protocol_2wire; extern struct ifd_protocol_ops ifd_protocol_3wire; extern struct ifd_protocol_ops ifd_protocol_eurochip; +extern struct ifd_protocol_ops ifd_protocol_esc; extern void ifd_acr30u_register(void); extern void ifd_cardman_register(void); diff -Nru openct-0.6.7/src/ifd/proto-escape.c openct-0.6.7-rfid/src/ifd/proto-escape.c --- openct-0.6.7/src/ifd/proto-escape.c 1970-01-01 01:00:00.000000000 +0100 +++ openct-0.6.7-rfid/src/ifd/proto-escape.c 2006-05-27 19:32:21.000000000 +0200 @@ -0,0 +1,77 @@ +/* + * Escape protocol - simply pass everything to the reader driver's escape() + * + * This is required for exporting access to vendor-specific CCID extensions, + * such as the Omnikey CardMan 5121 RFID support. + * + * The higher-level applications select a virtual slot (the last available slot + * number). This virtual slot will automatically get the IFD_PROTOCOL_ESCAPE + * assgigned to it and can then be used to transceive() data to/from the CCID. + * + * It's a bit ugly, but I was unable to come up with something cleaner. + * + * Copyright (C) 2005, Harald Welte + */ + +#include "internal.h" +#include +#include +#include + +static int +escape_init(ifd_protocol_t *prot) +{ + ifd_reader_t *reader = prot->reader; + const ifd_driver_t *drv; + + if (!reader || !(drv = reader->driver) + || !drv->ops || !drv->ops->escape) + return -1; + return 0; +} + +static void +escape_release(ifd_protocol_t *prot) +{ + /* NOP */ +} + +static int +escape_set_param(ifd_protocol_t *prot, int type, long value) +{ + ct_error("set_pameter not supported"); + return -1; +} + +static int +escape_get_param(ifd_protocol_t *prot, int type, long *result) +{ + ct_error("get_pameter not supported"); + return -1; +} + +static int +escape_transceive(ifd_protocol_t *prot, int dad, + const void *sbuf, size_t slen, + void *rbuf, size_t rlen) +{ + ifd_reader_t *reader = prot->reader; + const ifd_driver_t *drv = reader->driver; + + return drv->ops->escape(reader, dad, sbuf, slen, rbuf, rlen); +} + +struct ifd_protocol_ops ifd_protocol_esc = { + IFD_PROTOCOL_ESCAPE, /* id */ + "escape", /* name */ + sizeof(ifd_protocol_t), /* size */ + escape_init, /* init */ + escape_release, /* release */ + escape_set_param, /* set_param */ + escape_get_param, /* get_param */ + NULL, /* resynchronize */ + escape_transceive, /* transceive */ + NULL, /* sync_read */ + NULL, /* sync_write */ +}; + diff -Nru openct-0.6.7/src/include/openct/driver.h openct-0.6.7-rfid/src/include/openct/driver.h --- openct-0.6.7/src/include/openct/driver.h 2006-04-21 08:37:58.000000000 +0200 +++ openct-0.6.7-rfid/src/include/openct/driver.h 2006-05-27 19:32:21.000000000 +0200 @@ -318,6 +318,11 @@ int (*sync_write)(ifd_reader_t *reader, int slot, int proto, unsigned short addr, const unsigned char *sbuf, size_t slen); + + /*Support for transparent access to "escape" */ + int (*escape)(ifd_reader_t *reader, int slot, + void *sbuf, size_t slen, + void *rbuf, size_t rlen); }; extern void ifd_driver_register(const char *, diff -Nru openct-0.6.7/src/include/openct/ifd.h openct-0.6.7-rfid/src/include/openct/ifd.h --- openct-0.6.7/src/include/openct/ifd.h 2006-04-21 08:37:58.000000000 +0200 +++ openct-0.6.7-rfid/src/include/openct/ifd.h 2006-05-27 19:42:54.000000000 +0200 @@ -29,6 +29,8 @@ IFD_PROTOCOL_TLP, /* older Gemplus protocol */ IFD_PROTOCOL_GBP, /* Gemplus block protocol */ IFD_PROTOCOL_EUROCHIP, /* Eurochip Countercard */ + IFD_PROTOCOL_TCL, /* ISO 14443-4 T=CL */ + IFD_PROTOCOL_ESCAPE, /* Virtual 'escape' protocol */ IFD_PROTOCOL_TRANSPARENT = 128 };