allow multiple cards to connect to vpcd
due to limitations of pcscd this is currently limited to 10 cards. Note that there is a double free corruption in pcscd when unloading the driver.
This commit is contained in:
@@ -37,9 +37,10 @@ Currently the Virtual Smart Card supports the following types of smart cards:
|
|||||||
|
|
||||||
The |vpcd| is a smart card driver for PCSC-Lite_. It allows
|
The |vpcd| is a smart card driver for PCSC-Lite_. It allows
|
||||||
smart card applications to access the |vpicc| through the PC/SC API. By
|
smart card applications to access the |vpicc| through the PC/SC API. By
|
||||||
default |vpicc| communicates with |vpcd| through a socket on localhost port
|
default |vpcd| opens slots for communication with multiple |vpicc|'s on
|
||||||
35963. But the |vpicc| does not need to run on the same machine as the |vpcd|,
|
localhost from port 35963 to port 35972. But the |vpicc| does not need to run
|
||||||
they can connect over the internet for example.
|
on the same machine as the |vpcd|, they can connect over the internet for
|
||||||
|
example.
|
||||||
|
|
||||||
Although the Virtual Smart Card is a software emulator, you can use
|
Although the Virtual Smart Card is a software emulator, you can use
|
||||||
:ref:`pcsc-relay` to make it accessible to an external contact-less smart card
|
:ref:`pcsc-relay` to make it accessible to an external contact-less smart card
|
||||||
|
|||||||
@@ -37,9 +37,10 @@ Currently the @PACKAGE_NAME@ supports the following types of smart cards:
|
|||||||
|
|
||||||
The |vpcd| is a smart card driver for PCSC-Lite_. It allows
|
The |vpcd| is a smart card driver for PCSC-Lite_. It allows
|
||||||
smart card applications to access the |vpicc| through the PC/SC API. By
|
smart card applications to access the |vpicc| through the PC/SC API. By
|
||||||
default |vpicc| communicates with |vpcd| through a socket on localhost port
|
default |vpcd| opens slots for communication with multiple |vpicc|'s on
|
||||||
35963. But the |vpicc| does not need to run on the same machine as the |vpcd|,
|
localhost from port 35963 to port 35972. But the |vpicc| does not need to run
|
||||||
they can connect over the internet for example.
|
on the same machine as the |vpcd|, they can connect over the internet for
|
||||||
|
example.
|
||||||
|
|
||||||
Although the @PACKAGE_NAME@ is a software emulator, you can use
|
Although the @PACKAGE_NAME@ is a software emulator, you can use
|
||||||
:ref:`pcsc-relay` to make it accessible to an external contact-less smart card
|
:ref:`pcsc-relay` to make it accessible to an external contact-less smart card
|
||||||
|
|||||||
@@ -18,14 +18,28 @@
|
|||||||
|
|
||||||
#include "vpcd.h"
|
#include "vpcd.h"
|
||||||
|
|
||||||
|
/* pcscd allows at most 16 readers. We will use 10.
|
||||||
|
* See PCSCLITE_MAX_READERS_CONTEXTS in pcsclite.h */
|
||||||
|
#define VICC_MAX_SLOTS \
|
||||||
|
(PCSCLITE_MAX_READERS_CONTEXTS > 6 ? \
|
||||||
|
PCSCLITE_MAX_READERS_CONTEXTS-6 : \
|
||||||
|
1)
|
||||||
|
|
||||||
|
static struct vicc_ctx *ctx[VICC_MAX_SLOTS];
|
||||||
|
|
||||||
RESPONSECODE
|
RESPONSECODE
|
||||||
IFDHCreateChannel (DWORD Lun, DWORD Channel)
|
IFDHCreateChannel (DWORD Lun, DWORD Channel)
|
||||||
{
|
{
|
||||||
if (vicc_init(Channel) < 0) {
|
size_t slot = Lun & 0xffff;
|
||||||
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
|
ctx[slot] = vicc_init(Channel+slot);
|
||||||
|
if (!ctx[slot]) {
|
||||||
Log1(PCSC_LOG_ERROR, "Could not initialize connection to virtual ICC");
|
Log1(PCSC_LOG_ERROR, "Could not initialize connection to virtual ICC");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
Log2(PCSC_LOG_INFO, "Waiting for virtual ICC on port %hu", (unsigned short) Channel);
|
Log2(PCSC_LOG_INFO, "Waiting for virtual ICC on port %hu", (unsigned short) Channel+slot);
|
||||||
|
|
||||||
return IFD_SUCCESS;
|
return IFD_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -66,13 +80,19 @@ IFDHControl(DWORD Lun, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer,
|
|||||||
RESPONSECODE
|
RESPONSECODE
|
||||||
IFDHCloseChannel (DWORD Lun)
|
IFDHCloseChannel (DWORD Lun)
|
||||||
{
|
{
|
||||||
RESPONSECODE r = vicc_eject();
|
size_t slot = Lun & 0xffff;
|
||||||
if (vicc_exit() < 0) {
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
|
Log2(PCSC_LOG_ERROR, "Slot %u", slot);
|
||||||
|
if (vicc_exit(ctx[slot]) < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "Could not close connection to virtual ICC");
|
Log1(PCSC_LOG_ERROR, "Could not close connection to virtual ICC");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
|
ctx[slot] = NULL;
|
||||||
|
Log2(PCSC_LOG_ERROR, "Slot %u", slot);
|
||||||
|
|
||||||
return r;
|
return IFD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
RESPONSECODE
|
RESPONSECODE
|
||||||
@@ -80,6 +100,10 @@ IFDHGetCapabilities (DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value)
|
|||||||
{
|
{
|
||||||
unsigned char *atr = NULL;
|
unsigned char *atr = NULL;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
|
size_t slot = Lun & 0xffff;
|
||||||
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Length || !Value)
|
if (!Length || !Value)
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
@@ -87,7 +111,7 @@ IFDHGetCapabilities (DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value)
|
|||||||
switch (Tag) {
|
switch (Tag) {
|
||||||
case TAG_IFD_ATR:
|
case TAG_IFD_ATR:
|
||||||
|
|
||||||
size = vicc_getatr(&atr);
|
size = vicc_getatr(ctx[slot], &atr);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "could not get ATR");
|
Log1(PCSC_LOG_ERROR, "could not get ATR");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
@@ -115,6 +139,13 @@ IFDHGetCapabilities (DWORD Lun, DWORD Tag, PDWORD Length, PUCHAR Value)
|
|||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*Value = VICC_MAX_SLOTS;
|
||||||
|
*Length = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TAG_IFD_SLOT_THREAD_SAFE:
|
||||||
|
/* driver supports access to multiple slots of the same reader at
|
||||||
|
* the same time */
|
||||||
*Value = 1;
|
*Value = 1;
|
||||||
*Length = 1;
|
*Length = 1;
|
||||||
break;
|
break;
|
||||||
@@ -149,9 +180,13 @@ IFDHSetProtocolParameters (DWORD Lun, DWORD Protocol, UCHAR Flags, UCHAR PTS1,
|
|||||||
RESPONSECODE
|
RESPONSECODE
|
||||||
IFDHPowerICC (DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength)
|
IFDHPowerICC (DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength)
|
||||||
{
|
{
|
||||||
|
size_t slot = Lun & 0xffff;
|
||||||
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
switch (Action) {
|
switch (Action) {
|
||||||
case IFD_POWER_DOWN:
|
case IFD_POWER_DOWN:
|
||||||
if (vicc_poweroff() < 0) {
|
if (vicc_poweroff(ctx[slot]) < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "could not powerdown");
|
Log1(PCSC_LOG_ERROR, "could not powerdown");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
@@ -163,13 +198,13 @@ IFDHPowerICC (DWORD Lun, DWORD Action, PUCHAR Atr, PDWORD AtrLength)
|
|||||||
#endif
|
#endif
|
||||||
return IFD_SUCCESS;
|
return IFD_SUCCESS;
|
||||||
case IFD_POWER_UP:
|
case IFD_POWER_UP:
|
||||||
if (vicc_poweron() < 0) {
|
if (vicc_poweron(ctx[slot]) < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "could not powerup");
|
Log1(PCSC_LOG_ERROR, "could not powerup");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IFD_RESET:
|
case IFD_RESET:
|
||||||
if (vicc_reset() < 0) {
|
if (vicc_reset(ctx[slot]) < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "could not reset");
|
Log1(PCSC_LOG_ERROR, "could not reset");
|
||||||
return IFD_COMMUNICATION_ERROR;
|
return IFD_COMMUNICATION_ERROR;
|
||||||
}
|
}
|
||||||
@@ -190,13 +225,17 @@ IFDHTransmitToICC (DWORD Lun, SCARD_IO_HEADER SendPci, PUCHAR TxBuffer,
|
|||||||
unsigned char *rapdu = NULL;
|
unsigned char *rapdu = NULL;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
RESPONSECODE r = IFD_COMMUNICATION_ERROR;
|
RESPONSECODE r = IFD_COMMUNICATION_ERROR;
|
||||||
|
size_t slot = Lun & 0xffff;
|
||||||
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (!RxLength || !RecvPci) {
|
if (!RxLength || !RecvPci) {
|
||||||
Log1(PCSC_LOG_ERROR, "Invalid input data");
|
Log1(PCSC_LOG_ERROR, "Invalid input data");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = vicc_transmit(TxLength, TxBuffer, &rapdu);
|
size = vicc_transmit(ctx[slot], TxLength, TxBuffer, &rapdu);
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
Log1(PCSC_LOG_ERROR, "could not send apdu or receive rapdu");
|
Log1(PCSC_LOG_ERROR, "could not send apdu or receive rapdu");
|
||||||
@@ -226,7 +265,11 @@ err:
|
|||||||
RESPONSECODE
|
RESPONSECODE
|
||||||
IFDHICCPresence (DWORD Lun)
|
IFDHICCPresence (DWORD Lun)
|
||||||
{
|
{
|
||||||
switch (vicc_present()) {
|
size_t slot = Lun & 0xffff;
|
||||||
|
if (slot >= VICC_MAX_SLOTS) {
|
||||||
|
return IFD_COMMUNICATION_ERROR;
|
||||||
|
}
|
||||||
|
switch (vicc_present(ctx[slot])) {
|
||||||
case 0:
|
case 0:
|
||||||
return IFD_ICC_NOT_PRESENT;
|
return IFD_ICC_NOT_PRESENT;
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
@@ -43,11 +43,8 @@ typedef WORD uint16_t;
|
|||||||
#define VPCD_CTRL_RESET 2
|
#define VPCD_CTRL_RESET 2
|
||||||
#define VPCD_CTRL_ATR 4
|
#define VPCD_CTRL_ATR 4
|
||||||
|
|
||||||
static int server_sock = -1;
|
ssize_t sendToVICC(struct vicc_ctx *ctx, size_t size, const unsigned char *buffer);
|
||||||
static int client_sock = -1;
|
ssize_t recvFromVICC(struct vicc_ctx *ctx, unsigned char **buffer);
|
||||||
|
|
||||||
ssize_t sendToVICC(size_t size, const unsigned char *buffer);
|
|
||||||
ssize_t recvFromVICC(unsigned char **buffer);
|
|
||||||
|
|
||||||
static ssize_t sendall(int sock, const void *buffer, size_t size);
|
static ssize_t sendall(int sock, const void *buffer, size_t size);
|
||||||
static ssize_t recvall(int sock, void *buffer, size_t size);
|
static ssize_t recvall(int sock, void *buffer, size_t size);
|
||||||
@@ -135,37 +132,42 @@ int waitforclient(int server, long secs, long usecs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sendToVICC(size_t length, const unsigned char* buffer)
|
ssize_t sendToVICC(struct vicc_ctx *ctx, size_t length, const unsigned char* buffer)
|
||||||
{
|
{
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* send size of message on 2 bytes */
|
/* send size of message on 2 bytes */
|
||||||
size = htons((uint16_t) length);
|
size = htons((uint16_t) length);
|
||||||
r = sendall(client_sock, (void *) &size, sizeof size);
|
r = sendall(ctx->client_sock, (void *) &size, sizeof size);
|
||||||
if (r == sizeof size)
|
if (r == sizeof size)
|
||||||
/* send message */
|
/* send message */
|
||||||
r = sendall(client_sock, buffer, length);
|
r = sendall(ctx->client_sock, buffer, length);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
vicc_eject();
|
vicc_eject(ctx);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t recvFromVICC(unsigned char **buffer)
|
ssize_t recvFromVICC(struct vicc_ctx *ctx, unsigned char **buffer)
|
||||||
{
|
{
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
unsigned char *p = NULL;
|
unsigned char *p = NULL;
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer || !ctx) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive size of message on 2 bytes */
|
/* receive size of message on 2 bytes */
|
||||||
r = recvall(client_sock, &size, sizeof size);
|
r = recvall(ctx->client_sock, &size, sizeof size);
|
||||||
if (r < sizeof size)
|
if (r < sizeof size)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -179,57 +181,75 @@ ssize_t recvFromVICC(unsigned char **buffer)
|
|||||||
*buffer = p;
|
*buffer = p;
|
||||||
|
|
||||||
/* receive message */
|
/* receive message */
|
||||||
return recvall(client_sock, *buffer, size);
|
return recvall(ctx->client_sock, *buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_eject(void) {
|
int vicc_eject(struct vicc_ctx *ctx)
|
||||||
if (client_sock > 0) {
|
{
|
||||||
client_sock = close(client_sock);
|
if (ctx && ctx->client_sock > 0) {
|
||||||
if (client_sock < 0) {
|
ctx->client_sock = close(ctx->client_sock);
|
||||||
|
if (ctx->client_sock < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_init(unsigned short port) {
|
struct vicc_ctx * vicc_init(unsigned short port)
|
||||||
server_sock = opensock(port);
|
{
|
||||||
if (server_sock < 0)
|
struct vicc_ctx *ctx = malloc(sizeof *ctx);
|
||||||
return -1;
|
if (!ctx) {
|
||||||
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vicc_exit(void) {
|
|
||||||
if (server_sock > 0) {
|
|
||||||
server_sock = close(server_sock);
|
|
||||||
if (server_sock < 0) return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ctx->server_sock = opensock(port);
|
||||||
|
if (ctx->server_sock < 0) {
|
||||||
|
free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->client_sock = -1;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t vicc_transmit(size_t apdu_len,
|
int vicc_exit(struct vicc_ctx *ctx)
|
||||||
const unsigned char *apdu, unsigned char **rapdu)
|
|
||||||
{
|
{
|
||||||
ssize_t r;
|
int r = vicc_eject(ctx);
|
||||||
|
if (ctx) {
|
||||||
r = sendToVICC(apdu_len, apdu);
|
if (ctx->server_sock > 0) {
|
||||||
|
ctx->server_sock = close(ctx->server_sock);
|
||||||
if (r > 0)
|
if (ctx->server_sock < 0) {
|
||||||
r = recvFromVICC(rapdu);
|
r -= 1;
|
||||||
|
}
|
||||||
if (r <= 0)
|
}
|
||||||
vicc_eject();
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_present(void) {
|
ssize_t vicc_transmit(struct vicc_ctx *ctx,
|
||||||
|
size_t apdu_len, const unsigned char *apdu,
|
||||||
|
unsigned char **rapdu)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
r = sendToVICC(ctx, apdu_len, apdu);
|
||||||
|
|
||||||
|
if (r > 0)
|
||||||
|
r = recvFromVICC(ctx, rapdu);
|
||||||
|
|
||||||
|
if (r <= 0)
|
||||||
|
vicc_eject(ctx);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vicc_present(struct vicc_ctx *ctx) {
|
||||||
unsigned char *atr = NULL;
|
unsigned char *atr = NULL;
|
||||||
|
|
||||||
if (client_sock > 0) {
|
if (ctx->client_sock > 0) {
|
||||||
if (vicc_getatr(&atr) <= 0)
|
if (vicc_getatr(ctx, &atr) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free(atr);
|
free(atr);
|
||||||
@@ -237,31 +257,31 @@ int vicc_present(void) {
|
|||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
/* Wait up to one microsecond. */
|
/* Wait up to one microsecond. */
|
||||||
client_sock = waitforclient(server_sock, 0, 1);
|
ctx->client_sock = waitforclient(ctx->server_sock, 0, 1);
|
||||||
|
|
||||||
if (client_sock < 0)
|
if (ctx->client_sock < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t vicc_getatr(unsigned char **atr) {
|
ssize_t vicc_getatr(struct vicc_ctx *ctx, unsigned char **atr) {
|
||||||
unsigned char i = VPCD_CTRL_ATR;
|
unsigned char i = VPCD_CTRL_ATR;
|
||||||
return vicc_transmit(VPCD_CTRL_LEN, &i, atr);
|
return vicc_transmit(ctx, VPCD_CTRL_LEN, &i, atr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_poweron(void) {
|
int vicc_poweron(struct vicc_ctx *ctx) {
|
||||||
unsigned char i = VPCD_CTRL_ON;
|
unsigned char i = VPCD_CTRL_ON;
|
||||||
return sendToVICC(VPCD_CTRL_LEN, &i);
|
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_poweroff(void) {
|
int vicc_poweroff(struct vicc_ctx *ctx) {
|
||||||
unsigned char i = VPCD_CTRL_OFF;
|
unsigned char i = VPCD_CTRL_OFF;
|
||||||
return sendToVICC(VPCD_CTRL_LEN, &i);
|
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vicc_reset(void) {
|
int vicc_reset(struct vicc_ctx *ctx) {
|
||||||
unsigned char i = VPCD_CTRL_RESET;
|
unsigned char i = VPCD_CTRL_RESET;
|
||||||
return sendToVICC(VPCD_CTRL_LEN, &i);
|
return sendToVICC(ctx, VPCD_CTRL_LEN, &i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ typedef int ssize_t;
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct vicc_ctx {
|
||||||
|
int server_sock;
|
||||||
|
int client_sock;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -34,14 +39,14 @@ extern "C" {
|
|||||||
/** Standard port of the virtual smart card reader */
|
/** Standard port of the virtual smart card reader */
|
||||||
#define VPCDPORT 35963
|
#define VPCDPORT 35963
|
||||||
|
|
||||||
int vicc_init(unsigned short port);
|
struct vicc_ctx * vicc_init(unsigned short port);
|
||||||
int vicc_exit(void);
|
int vicc_exit(struct vicc_ctx *ctx);
|
||||||
int vicc_eject(void);
|
int vicc_eject(struct vicc_ctx *ctx);
|
||||||
|
|
||||||
int vicc_present(void);
|
int vicc_present(struct vicc_ctx *ctx);
|
||||||
int vicc_poweron(void);
|
int vicc_poweron(struct vicc_ctx *ctx);
|
||||||
int vicc_poweroff(void);
|
int vicc_poweroff(struct vicc_ctx *ctx);
|
||||||
int vicc_reset(void);
|
int vicc_reset(struct vicc_ctx *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Receive ATR from the virtual smart card.
|
* @brief Receive ATR from the virtual smart card.
|
||||||
@@ -52,7 +57,7 @@ int vicc_reset(void);
|
|||||||
* @return On success, the call returns the number of bytes received.
|
* @return On success, the call returns the number of bytes received.
|
||||||
* On error, -1 is returned, and errno is set appropriately.
|
* On error, -1 is returned, and errno is set appropriately.
|
||||||
*/
|
*/
|
||||||
ssize_t vicc_getatr(unsigned char** atr);
|
ssize_t vicc_getatr(struct vicc_ctx *ctx, unsigned char** atr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send an APDU to the virtual smart card.
|
* @brief Send an APDU to the virtual smart card.
|
||||||
@@ -66,7 +71,8 @@ ssize_t vicc_getatr(unsigned char** atr);
|
|||||||
* @return On success, the call returns the number of bytes received.
|
* @return On success, the call returns the number of bytes received.
|
||||||
* On error, -1 is returned, and errno is set appropriately.
|
* On error, -1 is returned, and errno is set appropriately.
|
||||||
*/
|
*/
|
||||||
ssize_t vicc_transmit(size_t apdu_len, const unsigned char *apdu,
|
ssize_t vicc_transmit(struct vicc_ctx *ctx,
|
||||||
|
size_t apdu_len, const unsigned char *apdu,
|
||||||
unsigned char **rapdu);
|
unsigned char **rapdu);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Reference in New Issue
Block a user