diff --git a/pcsc-relay/src/Makefile.am b/pcsc-relay/src/Makefile.am index 1adfc93..c749dbc 100644 --- a/pcsc-relay/src/Makefile.am +++ b/pcsc-relay/src/Makefile.am @@ -28,11 +28,11 @@ pcsc-relay.1: bin_PROGRAMS = pcsc-relay bin_SCRIPTS = picc.py -pcsc_relay_SOURCES = pcsc-relay.c pcsc.c opicc.c lnfc.c $(BUILT_SOURCES) +pcsc_relay_SOURCES = pcsc-relay.c pcsc.c vpcd.c vpcd-driver.c opicc.c lnfc.c $(BUILT_SOURCES) pcsc_relay_LDADD = $(PCSC_LIBS) $(LIBNFC_LIBS) pcsc_relay_CFLAGS = $(PCSC_CFLAGS) $(LIBNFC_CFLAGS) -noinst_HEADERS = pcsc-relay.h +noinst_HEADERS = pcsc-relay.h vpcd.h pcsc-relay.c: $(BUILT_SOURCES) diff --git a/pcsc-relay/src/pcsc-relay.c b/pcsc-relay/src/pcsc-relay.c index d8c4e77..7fcabd2 100644 --- a/pcsc-relay/src/pcsc-relay.c +++ b/pcsc-relay/src/pcsc-relay.c @@ -158,6 +158,18 @@ int main (int argc, char **argv) } readernum = args_info.reader_arg; + switch (args_info.connector_arg) { + case connector_arg_vicc: + scdriver = &driver_vpcd; + break; + case connector_arg_pcsc: + scdriver = &driver_pcsc; + break; + default: + exit(2); + } + vpcdport = args_info.port_arg; + #if HAVE_SIGACTION struct sigaction new_sig, old_sig; diff --git a/pcsc-relay/src/pcsc-relay.ggo.in b/pcsc-relay/src/pcsc-relay.ggo.in index a9b7a95..464edb0 100644 --- a/pcsc-relay/src/pcsc-relay.ggo.in +++ b/pcsc-relay/src/pcsc-relay.ggo.in @@ -1,15 +1,24 @@ purpose "Emulate a contact-less smart card" description "Using an contact-less interface (currently OpenPICC or libnfc) @PACKAGE@ receives command APDUs which are forwared to an existing smart card via PC/SC. @PACKAGE@ sends the response APDU back to the contact-less interface." -option "reader" r - "Number of the PC/SC reader to use (-1 for autodetect)" - int default="-1" - optional option "emulator" e "Contact-less emulator backend" values="libnfc","openpicc" default="libnfc" enum optional +option "connector" c + "Smart card connector backend" + values="pcsc","vicc" default="pcsc" + enum + optional +option "reader" r + "Number of the PC/SC reader to use (-1 for autodetect)" + int default="-1" + optional +option "port" p + "Port to listen for virtual smart card" + int default="35963" + optional option "foreground" f "Stay in foreground" flag off diff --git a/pcsc-relay/src/pcsc-relay.h b/pcsc-relay/src/pcsc-relay.h index fc8e39e..55172fa 100644 --- a/pcsc-relay/src/pcsc-relay.h +++ b/pcsc-relay/src/pcsc-relay.h @@ -55,6 +55,8 @@ struct sc_driver { extern struct sc_driver driver_pcsc; extern unsigned int readernum; +extern struct sc_driver driver_vpcd; +extern unsigned int vpcdport; #define LEVEL_INFO 1 #define LEVEL_DEBUG 2 diff --git a/pcsc-relay/src/vpcd-driver.c b/pcsc-relay/src/vpcd-driver.c new file mode 100644 index 0000000..360ba51 --- /dev/null +++ b/pcsc-relay/src/vpcd-driver.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Frank Morgner + * + * This file is part of pcsc-relay. + * + * pcsc-relay is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * pcsc-relay 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * pcsc-relay. If not, see . + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcsc-relay.h" +#include "vpcd.h" +#include +#include +#include + + + +unsigned int vpcdport = VPCDPORT; + + +static int vpcd_connect(driver_data_t **driver_data) +{ + int vicc_found = 0; + + + if (vicc_init(vpcdport) < 0) { + RELAY_ERROR("Could not initialize connection to virtual ICC\n"); + return 0; + } + INFO("Waiting for virtual ICC on port %hu\n", + (unsigned short) vpcdport); + + + do { + switch (vicc_present()) { + case 0: + /* not present */ + sleep(1); + break; + case 1: + vicc_found = 1; + break; + default: + RELAY_ERROR("Could not get ICC state\n"); + return 0; + } + } while (!vicc_found); + + + if (vicc_poweron() < 0) { + RELAY_ERROR("could not powerup\n"); + return 0; + } + + INFO("Connected to virtual ICC\n"); + + + return 1; +} + +static int vpcd_disconnect(driver_data_t *driver_data) +{ + if (vicc_eject() != 0) + DEBUG("Could not eject virtual ICC\n"); + + if (vicc_exit() != 0) { + RELAY_ERROR("Could not close connection to virtual ICC\n"); + return 0; + } + + return 1; +} + +static int vpcd_transmit(driver_data_t *driver_data, + const unsigned char *send, size_t send_len, + unsigned char *recv, size_t *recv_len) +{ + char *rapdu; + int size = vicc_transmit(send_len, (char *) send, &rapdu); + + if (size < 0) { + RELAY_ERROR("could not send apdu or receive rapdu\n"); + *recv_len = 0; + return 0; + } + + if (*recv_len < size) { + RELAY_ERROR("Not enough memory for rapdu\n"); + *recv_len = 0; + free(rapdu); + return 0; + } + + *recv_len = size; + memcpy(recv, rapdu, size); + free(rapdu); + + return 1; +} + + +struct sc_driver driver_vpcd = { + .connect = vpcd_connect, + .disconnect = vpcd_disconnect, + .transmit = vpcd_transmit, +}; diff --git a/pcsc-relay/src/vpcd.c b/pcsc-relay/src/vpcd.c new file mode 120000 index 0000000..272ab7d --- /dev/null +++ b/pcsc-relay/src/vpcd.c @@ -0,0 +1 @@ +../../virtualsmartcard/src/vpcd/vpcd.c \ No newline at end of file diff --git a/pcsc-relay/src/vpcd.h b/pcsc-relay/src/vpcd.h new file mode 120000 index 0000000..1b50d33 --- /dev/null +++ b/pcsc-relay/src/vpcd.h @@ -0,0 +1 @@ +../../virtualsmartcard/src/vpcd/vpcd.h \ No newline at end of file