use ACardEmulator as nfc backend for pcsc-relay
This feature is experimental and disabled by default At ACardEmulator's compile time it is required: - to add the correct application identifier to aid_list.xml - enable the connection to pcsc-relay by setting useVPCD
This commit is contained in:
@@ -29,7 +29,7 @@ $(abs_builddir)/pcsc-relay.1:
|
||||
bin_PROGRAMS = pcsc-relay
|
||||
bin_SCRIPTS = picc.py
|
||||
|
||||
pcsc_relay_SOURCES = pcsc-relay.c pcsc.c vpcd.c vpcd-driver.c opicc.c lnfc.c lock.c $(BUILT_SOURCES)
|
||||
pcsc_relay_SOURCES = pcsc-relay.c pcsc.c vpcd.c vpcd-driver.c opicc.c lnfc.c vicc.c lock.c $(BUILT_SOURCES)
|
||||
pcsc_relay_LDADD = $(PCSC_LIBS) $(LIBNFC_LIBS)
|
||||
pcsc_relay_CFLAGS = $(PCSC_CFLAGS) $(LIBNFC_CFLAGS)
|
||||
|
||||
|
||||
@@ -32,7 +32,13 @@
|
||||
#include "pcsc-relay.h"
|
||||
|
||||
#ifndef MAX_BUFFER_SIZE
|
||||
#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */
|
||||
/** Maximum Tx/Rx Buffer for short APDU */
|
||||
#define MAX_BUFFER_SIZE 261
|
||||
#endif
|
||||
|
||||
#ifndef MAX_EXT_BUFFER_SIZE
|
||||
/** Maximum Tx/Rx Buffer for extended APDU */
|
||||
#define MAX_EXT_BUFFER_SIZE 65538
|
||||
#endif
|
||||
|
||||
int verbose = 0;
|
||||
@@ -133,7 +139,7 @@ int main (int argc, char **argv)
|
||||
unsigned char *buf = NULL;
|
||||
size_t buflen;
|
||||
|
||||
unsigned char outputBuffer[MAX_BUFFER_SIZE];
|
||||
unsigned char outputBuffer[MAX_EXT_BUFFER_SIZE];
|
||||
size_t outputLength;
|
||||
|
||||
struct gengetopt_args_info args_info;
|
||||
@@ -205,8 +211,12 @@ int main (int argc, char **argv)
|
||||
|
||||
while(1) {
|
||||
/* get C-APDU */
|
||||
if (!rfdriver->receive_capdu(rfdriver_data, &buf, &buflen))
|
||||
goto err;
|
||||
if (!rfdriver->receive_capdu(rfdriver_data, &buf, &buflen)) {
|
||||
do {
|
||||
INFO("Trying to recover by reconnecting to emulator\n");
|
||||
sleep(10);
|
||||
} while (!rfdriver->connect(&rfdriver_data));
|
||||
}
|
||||
if (!buflen || !buf)
|
||||
continue;
|
||||
|
||||
@@ -223,8 +233,12 @@ int main (int argc, char **argv)
|
||||
/* send R-APDU */
|
||||
hexdump("R-APDU:\n", outputBuffer, outputLength);
|
||||
|
||||
if (!rfdriver->send_rapdu(rfdriver_data, outputBuffer, outputLength))
|
||||
goto err;
|
||||
if (!rfdriver->send_rapdu(rfdriver_data, outputBuffer, outputLength)) {
|
||||
do {
|
||||
INFO("Trying to recover by reconnecting to emulator\n");
|
||||
sleep(10);
|
||||
} while (!rfdriver->connect(&rfdriver_data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description "Using an contact-less interface (currently OpenPICC or libnfc) @PAC
|
||||
|
||||
option "emulator" e
|
||||
"Contact-less emulator backend"
|
||||
values="libnfc","openpicc" default="libnfc"
|
||||
values="libnfc","vpcd","openpicc" default="libnfc"
|
||||
enum
|
||||
optional
|
||||
option "connector" c
|
||||
|
||||
@@ -44,6 +44,7 @@ extern int verbose;
|
||||
|
||||
extern struct rf_driver driver_openpicc;
|
||||
extern struct rf_driver driver_libnfc;
|
||||
extern struct rf_driver driver_vicc;
|
||||
|
||||
struct sc_driver {
|
||||
int (*connect) (driver_data_t **driver_data);
|
||||
|
||||
138
pcsc-relay/src/vicc.c
Normal file
138
pcsc-relay/src/vicc.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pcsc-relay.h"
|
||||
#include "vpcd.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
static int _vicc_connect(driver_data_t **driver_data)
|
||||
{
|
||||
struct vicc_ctx *ctx;
|
||||
const long secs = 300;
|
||||
|
||||
if (!driver_data)
|
||||
return 0;
|
||||
|
||||
|
||||
ctx = vicc_init(NULL, vpcdport);
|
||||
if (!ctx) {
|
||||
RELAY_ERROR("Could not initialize connection to VPCD\n");
|
||||
return 0;
|
||||
}
|
||||
*driver_data = ctx;
|
||||
|
||||
INFO("Waiting for VPCD on port %hu for %ld seconds\n",
|
||||
(unsigned short) vpcdport, secs);
|
||||
if (vicc_connect(ctx, secs, 0))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vicc_disconnect(driver_data_t *driver_data)
|
||||
{
|
||||
struct vicc_ctx *ctx = driver_data;
|
||||
|
||||
vicc_eject(ctx);
|
||||
if (vicc_exit(ctx) != 0) {
|
||||
RELAY_ERROR("Could not close connection to virtual ICC\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int vicc_receive_capdu(driver_data_t *driver_data,
|
||||
unsigned char **capdu, size_t *len)
|
||||
{
|
||||
struct vicc_ctx *ctx = driver_data;
|
||||
|
||||
int r = 0;
|
||||
ssize_t size;
|
||||
const unsigned char atr[] = {0x3B, 0x80, 0x80, 0x01, 0x01};
|
||||
|
||||
if (!len)
|
||||
goto err;
|
||||
|
||||
do {
|
||||
size = vicc_transmit(ctx, 0, NULL, capdu);
|
||||
|
||||
if (size < 0) {
|
||||
RELAY_ERROR("could not receive request\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
switch (*capdu[0]) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
// ignore reset, power on, power off
|
||||
break;
|
||||
case 0x03:
|
||||
if (vicc_transmit(ctx, sizeof atr, atr, NULL) < 0) {
|
||||
RELAY_ERROR("could not send ATR\n");
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
RELAY_ERROR("Unknown request: 0x%0X\n", *capdu[0]);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
// finaly we got the capdu
|
||||
*len = size;
|
||||
r = 1;
|
||||
}
|
||||
} while (!r);
|
||||
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int vicc_send_rapdu(driver_data_t *driver_data,
|
||||
const unsigned char *rapdu, size_t len)
|
||||
{
|
||||
struct vicc_ctx *ctx = driver_data;
|
||||
|
||||
if (!ctx || !rapdu)
|
||||
return 0;
|
||||
|
||||
if (vicc_transmit(ctx, len, rapdu, NULL) < 0) {
|
||||
RELAY_ERROR("could not send R-APDU\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct rf_driver driver_vicc = {
|
||||
.connect = _vicc_connect,
|
||||
.disconnect = vicc_disconnect,
|
||||
.receive_capdu = vicc_receive_capdu,
|
||||
.send_rapdu = vicc_send_rapdu,
|
||||
};
|
||||
Reference in New Issue
Block a user