- added reader driver for usbtoken

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@960 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-03-27 10:14:22 +00:00
parent 995bcfa2df
commit da172fd4c5
4 changed files with 303 additions and 2 deletions

View File

@ -4,7 +4,7 @@ includedir = ${prefix}/include/opensc
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = Makefile.mak opensc-config.in
EXTRA_DIST = Makefile.mak libopensc.pc.in reader-pcsc.c
if HAVE_SSL
SSL_LIB = @LIBCRYPTO@
@ -27,7 +27,8 @@ libopensc_la_SOURCES = sc.c ctx.c module.c asn1.c log.c base64.c \
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
pkcs15-wrap.c pkcs15-algo.c \
pkcs15-cache.c $(PCSC_SRC) reader-ctapi.c ctbcs.c \
pkcs15-cache.c $(PCSC_SRC) reader-ctapi.c \
reader-usbtoken.c ctbcs.c \
card-setcos.c card-miocos.c card-flex.c card-gpk.c \
card-etoken.c card-tcos.c card-emv.c card-default.c \
card-mcrd.c
@ -39,3 +40,7 @@ include_HEADERS = opensc.h pkcs15.h emv.h \
errors.h types.h \
cardctl.h asn1.h log.h
noinst_HEADERS = ctbcs.h internal.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libopensc.pc

View File

@ -74,6 +74,7 @@ static const struct _sc_driver_entry internal_reader_drivers[] = {
#endif
#ifndef _WIN32
{ "ctapi", (void *) sc_get_ctapi_driver, NULL },
{ "usbtoken", (void *) sc_get_usbtoken_driver, NULL },
#endif
{ NULL, NULL, NULL }
};

View File

@ -791,6 +791,7 @@ extern const char *sc_get_version(void);
extern const struct sc_reader_driver *sc_get_pcsc_driver(void);
extern const struct sc_reader_driver *sc_get_ctapi_driver(void);
extern const struct sc_reader_driver *sc_get_usbtoken_driver(void);
extern struct sc_card_driver *sc_get_iso7816_driver(void);
extern struct sc_card_driver *sc_get_emv_driver(void);

View File

@ -0,0 +1,294 @@
/*
* reader-usbtoken.c: Reader driver for USBtoken
*
* Copyright (C) 2002 Andreas Jellinghaus <aj@dungeon.inka.de>
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include "opensc.h"
#include "internal.h"
#include "log.h"
/* we will create that many usbtoken readers */
#define READERS 5
#define CLISOCKET "/tmp/opensc-usbtoken.XXXXXX"
#define SRVSOCKET "/var/run/usbtoken/socket%d"
/* function declarations */
int usbtoken_reader_init(struct sc_context *ctx, void **priv_data);
int usbtoken_reader_finish(struct sc_context *ctx, void *priv_data);
int usbtoken_reader_release(struct sc_reader *reader);
int usbtoken_reader_detect_card_presence(struct sc_reader *reader,
struct sc_slot_info *slot);
int usbtoken_reader_connect(struct sc_reader *reader,
struct sc_slot_info *slot);
int usbtoken_reader_disconnect(struct sc_reader *reader,
struct sc_slot_info *slot, int action);
int usbtoken_reader_transmit(struct sc_reader *reader,
struct sc_slot_info *slot, const u8 *sendbuf, size_t sendsize,
u8 *recvbuf, size_t *recvsize, int control);
int usbtoken_reader_lock(struct sc_reader *reader,
struct sc_slot_info *slot);
int usbtoken_reader_unlock(struct sc_reader *reader,
struct sc_slot_info *slot);
/* the operations struct, already initialized */
static struct sc_reader_operations usbtoken_reader_operations = {
.init = usbtoken_reader_init,
.finish = usbtoken_reader_finish,
.release = usbtoken_reader_release,
.detect_card_presence = usbtoken_reader_detect_card_presence,
.connect = usbtoken_reader_connect,
.disconnect = usbtoken_reader_disconnect,
.transmit = usbtoken_reader_transmit,
.lock = usbtoken_reader_lock,
.unlock = usbtoken_reader_unlock,
};
/* also, the driver struct */
static struct sc_reader_driver usbtoken_reader_driver = {
.name = "USB Crypto Token Reader",
.short_name = "usbtoken",
.ops = &usbtoken_reader_operations
};
/* return our structure */
const struct sc_reader_driver *sc_get_usbtoken_driver() {
return &usbtoken_reader_driver;
};
/* private data structures */
struct usbtoken_privslot {
struct sockaddr_un sa_un;
int slot, fd;
};
/* ok,lets start the real code */
int usbtoken_reader_init(struct sc_context *ctx, void **priv_data) {
/* Called during sc_establish_context(), when the driver
* is loaded */
int i;
struct sc_reader *myreader;
struct usbtoken_privslot *myprivslot;
SC_FUNC_CALLED(ctx, 1);
for (i=0; i< READERS; i++) {
myreader = malloc(sizeof(struct sc_reader));
bzero(myreader,sizeof(struct sc_reader));
myreader->driver = &usbtoken_reader_driver;
myreader->ops = &usbtoken_reader_operations;
myreader->slot_count = 1;
myreader->name =strdup("USB Crypto Token");
myprivslot = malloc(sizeof(struct usbtoken_privslot));
bzero(myprivslot,sizeof(struct usbtoken_privslot));
myreader->slot[0].drv_data=myprivslot;
myprivslot->sa_un.sun_family=AF_UNIX;
snprintf(myprivslot->sa_un.sun_path,
sizeof(myprivslot->sa_un.sun_path), SRVSOCKET, i);
if ( _sc_add_reader(ctx, myreader) != 0) {
/* error */
free(myprivslot);
free(myreader->name);
free(myreader);
break;
}
}
return SC_NO_ERROR;
}
int usbtoken_reader_finish(struct sc_context *ctx, void *priv_data) {
/* Called when the driver is being unloaded. finish() has to
* deallocate the private data and any resources. */
SC_FUNC_CALLED(ctx, 1);
return SC_NO_ERROR;
}
int usbtoken_reader_release(struct sc_reader *reader) {
/* Called when releasing a reader. release() has to
* deallocate the private data. Other fields will be
* freed by OpenSC. */
struct usbtoken_privslot *myprivslot;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = reader->slot[0].drv_data;
if (myprivslot) {
close (myprivslot->fd);
free(myprivslot);
}
return SC_NO_ERROR;
}
int usbtoken_reader_detect_card_presence(struct sc_reader *reader,
struct sc_slot_info *slot) {
struct usbtoken_privslot *myprivslot;
struct stat statbuf;
int rc;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = slot->drv_data;
rc = stat(myprivslot->sa_un.sun_path, &statbuf);
if (rc == -1)
slot->flags = 0;
else
slot->flags = SC_SLOT_CARD_PRESENT;
return slot->flags;
}
int usbtoken_reader_unix_cmd(struct sc_reader *reader,
struct sc_slot_info *slot,
u8 cmd) {
struct usbtoken_privslot *myprivslot;
u8 msg;
int rc;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = slot->drv_data;
rc = write(myprivslot->fd, &cmd, sizeof(cmd));
if (rc != sizeof(cmd)) {
error(reader->ctx, "usbtoken_reader_unix_cmd write failed\n");
return SC_ERROR_READER;
}
rc = read(myprivslot->fd, &msg, sizeof(msg));
if (rc != 1 || msg != 0) {
error(reader->ctx, "usbtoken_reader_unix_cmd read failed\n");
return SC_ERROR_READER;
}
return SC_NO_ERROR;
}
int usbtoken_reader_connect(struct sc_reader *reader,
struct sc_slot_info *slot) {
struct usbtoken_privslot *myprivslot;
int rc,len;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = slot->drv_data;
rc = socket(AF_UNIX, SOCK_STREAM, 0);
if (rc < 0) {
error(reader->ctx, "usbtoken_reader_connect socket failed\n");
return SC_ERROR_READER;
}
myprivslot->fd = rc;
len = sizeof(myprivslot->sa_un.sun_family) +
strlen(myprivslot->sa_un.sun_path);
rc = connect(myprivslot->fd, (struct sockaddr *)
&(myprivslot->sa_un), len);
if (rc < 0) {
close(myprivslot->fd);
myprivslot->fd=0;
error(reader->ctx, "usbtoken_reader_connect connect failed\n");
return SC_ERROR_CARD_NOT_PRESENT;
}
rc = read(myprivslot->fd, slot->atr, SC_MAX_ATR_SIZE);
if (rc == -1) {
error(reader->ctx, "usbtoken_reader_connect read failed\n");
return SC_ERROR_READER;
}
if (rc == 0) {
error(reader->ctx, "usbtoken_reader_connect recved no data\n");
return SC_ERROR_READER;
}
slot->atr_len = rc;
return SC_NO_ERROR;
}
int usbtoken_reader_disconnect(struct sc_reader *reader,
struct sc_slot_info *slot, int action) {
struct usbtoken_privslot *myprivslot;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = slot->drv_data;
close (myprivslot->fd);
return SC_NO_ERROR;
}
int usbtoken_reader_transmit(struct sc_reader *reader,
struct sc_slot_info *slot, const u8 *sendbuf, size_t sendsize,
u8 *recvbuf, size_t *recvsize, int control) {
struct usbtoken_privslot *myprivslot;
u8 buffer[1024];
int rc;
SC_FUNC_CALLED(reader->ctx, 1);
myprivslot = slot->drv_data;
if (sendsize > 1023) {
error(reader->ctx, "usbtoken_reader_transmit sendsize %d too big\n", sendsize);
return SC_ERROR_READER;
}
buffer[0] = 3;
memcpy(&buffer[1],sendbuf, sendsize);
rc = write (myprivslot->fd, buffer, sendsize+1);
if (rc != sendsize+1) {
error(reader->ctx, "usbtoken_reader_transmit write failed\n");
return SC_ERROR_READER;
}
rc = read(myprivslot->fd, buffer, sizeof(buffer));
if (rc == -1) {
error(reader->ctx, "usbtoken_reader_transmit read failed\n");
return SC_ERROR_READER;
}
if (rc == 0) {
error(reader->ctx, "usbtoken_reader_transmit recved no data\n");
return SC_ERROR_READER;
}
if (buffer[0] != 3) {
error(reader->ctx, "usbtoken_reader_transmit token failed\n");
return SC_ERROR_READER;
}
if (rc-1 > *recvsize) {
error(reader->ctx, "usbtoken_reader_transmit recved too much (%d > %d)\n", rc-1, *recvsize);
return SC_ERROR_READER;
}
*recvsize = rc -1;
memcpy(recvbuf,&buffer[1], rc-1);
return SC_NO_ERROR;
}
int usbtoken_reader_lock(struct sc_reader *reader,
struct sc_slot_info *slot) {
SC_FUNC_CALLED(reader->ctx, 1);
return usbtoken_reader_unix_cmd(reader, slot, 4);
}
int usbtoken_reader_unlock(struct sc_reader *reader,
struct sc_slot_info *slot) {
SC_FUNC_CALLED(reader->ctx, 1);
return usbtoken_reader_unix_cmd(reader, slot, 5);
}