mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
* configure.ac (HAVE_LIBUSB): Added a simple test for libusb.
* scdaemon.c, scdaemon.h: New option --pcsc-ccid. * ccid-driver.c, ccid-driver.h: New but far from being useful. * Makefile.am: Add above. * apdu.c: Add support for that ccid driver.
This commit is contained in:
parent
93c76df907
commit
936250aac9
@ -1,3 +1,7 @@
|
|||||||
|
2003-09-02 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* configure.ac (HAVE_LIBUSB): Added a simple test for libusb.
|
||||||
|
|
||||||
2003-08-19 Marcus Brinkmann <marcus@g10code.de>
|
2003-08-19 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac (AM_PATH_GPG_ERROR): Add missing comma in
|
* configure.ac (AM_PATH_GPG_ERROR): Add missing comma in
|
||||||
|
3
TODO
3
TODO
@ -20,6 +20,9 @@ might want to have an agent context for each service request
|
|||||||
** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent.
|
** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent.
|
||||||
** figure out how to auto retrieve a key by serialno+issuer.
|
** figure out how to auto retrieve a key by serialno+issuer.
|
||||||
Dirmngr is currently not able to parse more than the CN.
|
Dirmngr is currently not able to parse more than the CN.
|
||||||
|
** Try all available root certs in case we have several of them in our keybox.
|
||||||
|
For example TC TrustCenter Class 1 CA certs are ambiguous becuase
|
||||||
|
user certs don't come with a authorityKeyIdentifier.
|
||||||
|
|
||||||
* sm/decrypt.c
|
* sm/decrypt.c
|
||||||
** replace leading zero in integer hack by a cleaner solution
|
** replace leading zero in integer hack by a cleaner solution
|
||||||
|
@ -39,6 +39,10 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash)
|
|||||||
char * p, tmp[16];
|
char * p, tmp[16];
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
|
#warning I do do like that stuff - libgcrypt provides easier interfaces. -wk
|
||||||
|
/* FIXME: Either use the build function or create canonical encoded
|
||||||
|
S-expressions. */
|
||||||
|
|
||||||
p = xmalloc (64 + 2 * mdlen);
|
p = xmalloc (64 + 2 * mdlen);
|
||||||
s = gcry_md_algo_name (algo);
|
s = gcry_md_algo_name (algo);
|
||||||
if (s && strlen (s) < 16)
|
if (s && strlen (s) < 16)
|
||||||
|
13
configure.ac
13
configure.ac
@ -376,6 +376,19 @@ AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION",
|
|||||||
#
|
#
|
||||||
AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no)
|
AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no)
|
||||||
|
|
||||||
|
#
|
||||||
|
# libusb allows us to use the integrated CCID smartcard reader driver.
|
||||||
|
|
||||||
|
# Note, that we need the CVS version. FIXME: libusb should have a
|
||||||
|
# regular check as the other libraries do.
|
||||||
|
|
||||||
|
AC_CHECK_LIB(usb, usb_find_device,
|
||||||
|
[ LIBUSB_LIBS="$LIBUSB_LIBS -lusb"
|
||||||
|
AC_DEFINE(HAVE_LIBUSB,1,
|
||||||
|
[defined if libusb is available])
|
||||||
|
])
|
||||||
|
AC_SUBST(LIBUSB_LIBS)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# OpenSC is needed by the SCdaemon - if it is not availbale we can only
|
# OpenSC is needed by the SCdaemon - if it is not availbale we can only
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
* pkglue.c (mpi_from_sexp): New. Used to factor out
|
* pkglue.c (mpi_from_sexp): New. Used to factor out
|
||||||
some common code.
|
some common code.
|
||||||
|
|
||||||
|
2003-08-24 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* keygen.c (do_generate_keypair): Print a reminder to use --gen-revoke.
|
||||||
|
|
||||||
2003-08-18 Timo Schulz <twoaday@freakmail.de>
|
2003-08-18 Timo Schulz <twoaday@freakmail.de>
|
||||||
|
|
||||||
* encode.c (encode_sesskey): Checked the code and removed
|
* encode.c (encode_sesskey): Checked the code and removed
|
||||||
|
@ -2655,6 +2655,15 @@ do_generate_keypair (struct para_data_s *para,
|
|||||||
"the command \"--edit-key\" to generate a "
|
"the command \"--edit-key\" to generate a "
|
||||||
"secondary key for this purpose.\n"));
|
"secondary key for this purpose.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opt.batch && card)
|
||||||
|
{
|
||||||
|
tty_printf(_(
|
||||||
|
"Please create a revocation certificate now, so that you are able\n"
|
||||||
|
"to revoke the key if it ever happens that you lose your card or\n"
|
||||||
|
"the card gets damaged. Use the command \"--gen-revoke\".\n"
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2003-09-02 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
|
* scdaemon.c, scdaemon.h: New option --pcsc-ccid.
|
||||||
|
* ccid-driver.c, ccid-driver.h: New but far from being useful.
|
||||||
|
* Makefile.am: Add above.
|
||||||
|
* apdu.c: Add support for that ccid driver.
|
||||||
|
|
||||||
2003-08-26 Timo Schulz <twoaday@freakmail.de>
|
2003-08-26 Timo Schulz <twoaday@freakmail.de>
|
||||||
|
|
||||||
* apdu.c (new_reader_slot): Only set 'is_osc' when OpenSC
|
* apdu.c (new_reader_slot): Only set 'is_osc' when OpenSC
|
||||||
|
@ -32,17 +32,19 @@ scdaemon_SOURCES = \
|
|||||||
card-common.h \
|
card-common.h \
|
||||||
card-p15.c card-dinsig.c \
|
card-p15.c card-dinsig.c \
|
||||||
apdu.c apdu.h \
|
apdu.c apdu.h \
|
||||||
|
ccid-driver.c ccid-driver.h \
|
||||||
iso7816.c iso7816.h \
|
iso7816.c iso7816.h \
|
||||||
app.c app-common.h \
|
app.c app-common.h \
|
||||||
app-openpgp.c
|
app-openpgp.c
|
||||||
|
|
||||||
scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
|
scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \
|
||||||
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \
|
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \
|
||||||
-lgpg-error @INTLLIBS@ -ldl
|
$(LIBUSB_LIBS) -lgpg-error @INTLLIBS@ -ldl
|
||||||
|
|
||||||
sc_investigate_SOURCES = \
|
sc_investigate_SOURCES = \
|
||||||
sc-investigate.c scdaemon.h \
|
sc-investigate.c scdaemon.h \
|
||||||
apdu.c apdu.h \
|
apdu.c apdu.h \
|
||||||
|
ccid-driver.c ccid-driver.h \
|
||||||
iso7816.c iso7816.h \
|
iso7816.c iso7816.h \
|
||||||
app.c app-common.h \
|
app.c app-common.h \
|
||||||
app-openpgp.c \
|
app-openpgp.c \
|
||||||
@ -50,12 +52,14 @@ sc_investigate_SOURCES = \
|
|||||||
|
|
||||||
sc_investigate_LDADD = \
|
sc_investigate_LDADD = \
|
||||||
../jnlib/libjnlib.a ../common/libcommon.a \
|
../jnlib/libjnlib.a ../common/libcommon.a \
|
||||||
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl
|
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) @INTLLIBS@ \
|
||||||
|
-lgpg-error -ldl
|
||||||
|
|
||||||
|
|
||||||
sc_copykeys_SOURCES = \
|
sc_copykeys_SOURCES = \
|
||||||
sc-copykeys.c scdaemon.h \
|
sc-copykeys.c scdaemon.h \
|
||||||
apdu.c apdu.h \
|
apdu.c apdu.h \
|
||||||
|
ccid-driver.c ccid-driver.h \
|
||||||
iso7816.c iso7816.h \
|
iso7816.c iso7816.h \
|
||||||
app.c app-common.h \
|
app.c app-common.h \
|
||||||
app-openpgp.c \
|
app-openpgp.c \
|
||||||
@ -64,7 +68,8 @@ sc_copykeys_SOURCES = \
|
|||||||
sc_copykeys_LDADD = \
|
sc_copykeys_LDADD = \
|
||||||
../jnlib/libjnlib.a ../common/libcommon.a \
|
../jnlib/libjnlib.a ../common/libcommon.a \
|
||||||
../common/libsimple-pwquery.a \
|
../common/libsimple-pwquery.a \
|
||||||
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl
|
$(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) \
|
||||||
|
-lgpg-error @INTLLIBS@ -ldl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
96
scd/apdu.c
96
scd/apdu.c
@ -31,6 +31,7 @@
|
|||||||
#include "scdaemon.h"
|
#include "scdaemon.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "dynload.h"
|
#include "dynload.h"
|
||||||
|
#include "ccid-driver.h"
|
||||||
|
|
||||||
#define MAX_READER 4 /* Number of readers we support concurrently. */
|
#define MAX_READER 4 /* Number of readers we support concurrently. */
|
||||||
#define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for
|
#define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for
|
||||||
@ -42,6 +43,10 @@
|
|||||||
struct reader_table_s {
|
struct reader_table_s {
|
||||||
int used; /* True if slot is used. */
|
int used; /* True if slot is used. */
|
||||||
unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */
|
unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */
|
||||||
|
int is_ccid; /* Uses the internal CCID driver. */
|
||||||
|
struct {
|
||||||
|
ccid_driver_t handle;
|
||||||
|
} ccid;
|
||||||
int is_ctapi; /* This is a ctAPI driver. */
|
int is_ctapi; /* This is a ctAPI driver. */
|
||||||
struct {
|
struct {
|
||||||
unsigned long context;
|
unsigned long context;
|
||||||
@ -155,6 +160,7 @@ new_reader_slot (void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
reader_table[reader].used = 1;
|
reader_table[reader].used = 1;
|
||||||
|
reader_table[reader].is_ccid = 0;
|
||||||
reader_table[reader].is_ctapi = 0;
|
reader_table[reader].is_ctapi = 0;
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
reader_table[reader].is_osc = 0;
|
reader_table[reader].is_osc = 0;
|
||||||
@ -166,7 +172,9 @@ new_reader_slot (void)
|
|||||||
static void
|
static void
|
||||||
dump_reader_status (int reader)
|
dump_reader_status (int reader)
|
||||||
{
|
{
|
||||||
if (reader_table[reader].is_ctapi)
|
if (reader_table[reader].is_ccid)
|
||||||
|
log_info ("reader slot %d: using ccid driver\n", reader);
|
||||||
|
else if (reader_table[reader].is_ctapi)
|
||||||
{
|
{
|
||||||
log_info ("reader slot %d: %s\n", reader,
|
log_info ("reader slot %d: %s\n", reader,
|
||||||
reader_table[reader].status == 1? "Processor ICC present" :
|
reader_table[reader].status == 1? "Processor ICC present" :
|
||||||
@ -549,7 +557,74 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
|||||||
return err? -1:0; /* FIXME: Return appropriate error code. */
|
return err? -1:0; /* FIXME: Return appropriate error code. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
/*
|
||||||
|
Internal CCID driver interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_ccid_reader (void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
int slot;
|
||||||
|
reader_table_t slotp;
|
||||||
|
|
||||||
|
slot = new_reader_slot ();
|
||||||
|
if (slot == -1)
|
||||||
|
return -1;
|
||||||
|
slotp = reader_table + slot;
|
||||||
|
|
||||||
|
err = ccid_open_reader (&slotp->ccid.handle, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
slotp->used = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ccid_get_atr (slotp->ccid.handle,
|
||||||
|
slotp->atr, sizeof slotp->atr, &slotp->atrlen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
slotp->used = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
slotp->is_ccid = 1;
|
||||||
|
|
||||||
|
dump_reader_status (slot);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Actually send the APDU of length APDULEN to SLOT and return a
|
||||||
|
maximum of *BUFLEN data in BUFFER, the actual returned size will be
|
||||||
|
set to BUFLEN. Returns: Internal CCID driver error code. */
|
||||||
|
static int
|
||||||
|
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||||
|
unsigned char *buffer, size_t *buflen)
|
||||||
|
{
|
||||||
|
long err;
|
||||||
|
size_t maxbuflen;
|
||||||
|
|
||||||
|
if (DBG_CARD_IO)
|
||||||
|
log_printhex (" APDU_data:", apdu, apdulen);
|
||||||
|
|
||||||
|
maxbuflen = *buflen;
|
||||||
|
err = ccid_transceive (reader_table[slot].ccid.handle,
|
||||||
|
apdu, apdulen,
|
||||||
|
buffer, maxbuflen, buflen);
|
||||||
|
if (err)
|
||||||
|
log_error ("ccid_transceive failed: (0x%lx)\n",
|
||||||
|
err);
|
||||||
|
|
||||||
|
return err? -1:0; /* FIXME: Return appropriate error code. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
/*
|
/*
|
||||||
OpenSC Interface.
|
OpenSC Interface.
|
||||||
@ -755,6 +830,17 @@ apdu_open_reader (const char *portstr)
|
|||||||
{
|
{
|
||||||
static int pcsc_api_loaded, ct_api_loaded;
|
static int pcsc_api_loaded, ct_api_loaded;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
if (!opt.disable_ccid)
|
||||||
|
{
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
slot = open_ccid_reader ();
|
||||||
|
if (slot != -1)
|
||||||
|
return slot; /* got one */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
if (!opt.disable_opensc)
|
if (!opt.disable_opensc)
|
||||||
{
|
{
|
||||||
@ -871,6 +957,10 @@ error_string (int slot, long rc)
|
|||||||
return "[invalid slot]";
|
return "[invalid slot]";
|
||||||
if (reader_table[slot].is_ctapi)
|
if (reader_table[slot].is_ctapi)
|
||||||
return ct_error_string (rc);
|
return ct_error_string (rc);
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
else if (reader_table[slot].is_ccid)
|
||||||
|
return "no CCID driver error strings yet";
|
||||||
|
#endif
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
else if (reader_table[slot].is_osc)
|
else if (reader_table[slot].is_osc)
|
||||||
return sc_strerror (rc);
|
return sc_strerror (rc);
|
||||||
@ -889,6 +979,10 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
|||||||
return SW_HOST_NO_DRIVER;
|
return SW_HOST_NO_DRIVER;
|
||||||
if (reader_table[slot].is_ctapi)
|
if (reader_table[slot].is_ctapi)
|
||||||
return ct_send_apdu (slot, apdu, apdulen, buffer, buflen);
|
return ct_send_apdu (slot, apdu, apdulen, buffer, buflen);
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
else if (reader_table[slot].is_ccid)
|
||||||
|
return send_apdu_ccid (slot, apdu, apdulen, buffer, buflen);
|
||||||
|
#endif
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
else if (reader_table[slot].is_osc)
|
else if (reader_table[slot].is_osc)
|
||||||
return osc_send_apdu (slot, apdu, apdulen, buffer, buflen);
|
return osc_send_apdu (slot, apdu, apdulen, buffer, buflen);
|
||||||
|
627
scd/ccid-driver.c
Normal file
627
scd/ccid-driver.c
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
|
||||||
|
* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* CCID (ChipCardInterfaceDevices) is a specification for accessing
|
||||||
|
smartcard via a reader connected to the USB.
|
||||||
|
|
||||||
|
This is a limited driver allowing to use some CCID drivers directly
|
||||||
|
without any other specila drivers. This is a fallback driver to be
|
||||||
|
used when nothing else works or the system should be kept minimal
|
||||||
|
for security reasons. It makes use of the libusb library to gain
|
||||||
|
portable access to USB.
|
||||||
|
|
||||||
|
This driver has been tested with the SCM SCR335 smartcard reader
|
||||||
|
and requires that reader implements the TPDU level exchange and
|
||||||
|
does fully automatic initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LIBUSB) || defined(TEST)
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "ccid-driver.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RDR_to_PC_NotifySlotChange= 0x50,
|
||||||
|
RDR_to_PC_HardwareError = 0x51,
|
||||||
|
|
||||||
|
PC_to_RDR_SetParameters = 0x61,
|
||||||
|
PC_to_RDR_IccPowerOn = 0x62,
|
||||||
|
PC_to_RDR_IccPowerOff = 0x63,
|
||||||
|
PC_to_RDR_GetSlotStatus = 0x65,
|
||||||
|
PC_to_RDR_Secure = 0x69,
|
||||||
|
PC_to_RDR_T0APDU = 0x6a,
|
||||||
|
PC_to_RDR_Escape = 0x6b,
|
||||||
|
PC_to_RDR_GetParameters = 0x6c,
|
||||||
|
PC_to_RDR_ResetParameters = 0x6d,
|
||||||
|
PC_to_RDR_IccClock = 0x6e,
|
||||||
|
PC_to_RDR_XfrBlock = 0x6f,
|
||||||
|
PC_to_RDR_Mechanical = 0x71,
|
||||||
|
PC_to_RDR_Abort = 0x72,
|
||||||
|
PC_to_RDR_SetDataRate = 0x73,
|
||||||
|
|
||||||
|
RDR_to_PC_DataBlock = 0x80,
|
||||||
|
RDR_to_PC_SlotStatus = 0x81,
|
||||||
|
RDR_to_PC_Parameters = 0x82,
|
||||||
|
RDR_to_PC_Escape = 0x83,
|
||||||
|
RDR_to_PC_DataRate = 0x84
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Store information on the driver's state. A pointer to such a
|
||||||
|
structure is used as handle for most functions. */
|
||||||
|
struct ccid_driver_s {
|
||||||
|
usb_dev_handle *idev;
|
||||||
|
int seqno;
|
||||||
|
unsigned char t1_seqno;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Open the reader with the internal number READERNO and return a a
|
||||||
|
pointer to be used as handle in HANDLE. Returns 0 on success. */
|
||||||
|
int
|
||||||
|
ccid_open_reader (ccid_driver_t *handle, int readerno)
|
||||||
|
{
|
||||||
|
static int initialized;
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
usb_match_handle *match = NULL;
|
||||||
|
struct usb_device *dev = NULL;
|
||||||
|
usb_dev_handle *idev = NULL;
|
||||||
|
|
||||||
|
*handle = NULL;
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
usb_init ();
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = usb_create_match (&match, -1, -1, 11, -1, -1);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: usb_create_match failed: %d\n", rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (usb_find_device(match, dev, &dev) >= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ccid-driver: %-40s %04X/%04X\n", dev->filename,
|
||||||
|
dev->descriptor->idVendor, dev->descriptor->idProduct);
|
||||||
|
if (!readerno)
|
||||||
|
{
|
||||||
|
rc = usb_open (dev, &idev);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: usb_open failed: %d\n", rc);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = usb_claim_interface (idev, 0);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: usb_claim_interface failed: %d\n",
|
||||||
|
rc);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
*handle = calloc (1, sizeof **handle);
|
||||||
|
if (!*handle)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: out of memory\n");
|
||||||
|
rc = -1;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
(*handle)->idev = idev;
|
||||||
|
idev = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
readerno--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (idev)
|
||||||
|
usb_close (idev);
|
||||||
|
/* fixme: Do we need to release dev or is it supposed to be a
|
||||||
|
shallow copy of the list created internally by usb_init ? */
|
||||||
|
usb_free_match (match);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return False if a card is present and powered. */
|
||||||
|
int
|
||||||
|
ccid_check_card_presence (ccid_driver_t handle)
|
||||||
|
{
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_msg_len (unsigned char *msg, unsigned int length)
|
||||||
|
{
|
||||||
|
msg[1] = length;
|
||||||
|
msg[2] = length >> 8;
|
||||||
|
msg[3] = length >> 16;
|
||||||
|
msg[4] = length >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a MSG of length MSGLEN to the designated bulk out endpoint.
|
||||||
|
Returns 0 on success. */
|
||||||
|
static int
|
||||||
|
bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = usb_bulk_write (handle->idev,
|
||||||
|
1, /*endpoint */
|
||||||
|
msg, msglen,
|
||||||
|
1000 /* ms timeout */);
|
||||||
|
if (rc == msglen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
fprintf (stderr, "ccid-driver: usb_bulk_write error: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
else
|
||||||
|
fprintf (stderr, "ccid-driver: usb_bulk_write failed: %d\n", rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a maximum of LENGTH bytes from the bulk in endpoint into
|
||||||
|
BUFFER and return the actual read number if bytes in NREAD.
|
||||||
|
Returns 0 on success. */
|
||||||
|
static int
|
||||||
|
bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
|
||||||
|
size_t *nread)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = usb_bulk_read (handle->idev,
|
||||||
|
0x82,
|
||||||
|
buffer, length,
|
||||||
|
1000 /* ms timeout */ );
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: usb_bulk_read error: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nread = rc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* experimental */
|
||||||
|
int
|
||||||
|
ccid_poll (ccid_driver_t handle)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char msg[10];
|
||||||
|
size_t msglen;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
rc = usb_bulk_read (handle->idev,
|
||||||
|
0x83,
|
||||||
|
msg, sizeof msg,
|
||||||
|
0 /* ms timeout */ );
|
||||||
|
if (rc < 0 && errno == ETIMEDOUT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: usb_intr_read error: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msglen = rc;
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
if (msglen < 1)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: intr-in msg too short\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg[0] == RDR_to_PC_NotifySlotChange)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: notify slot change:");
|
||||||
|
for (i=1; i < msglen; i++)
|
||||||
|
for (j=0; j < 4; j++)
|
||||||
|
fprintf (stderr, " %d:%c%c",
|
||||||
|
(i-1)*4+j,
|
||||||
|
(msg[i] & (1<<(j*2)))? 'p':'-',
|
||||||
|
(msg[i] & (2<<(j*2)))? '*':' ');
|
||||||
|
putc ('\n', stderr);
|
||||||
|
}
|
||||||
|
else if (msg[0] == RDR_to_PC_HardwareError)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: hardware error occured\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unknown intr-in msg of type %02X\n",
|
||||||
|
msg[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ccid_slot_status (ccid_driver_t handle)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char msg[100];
|
||||||
|
size_t msglen;
|
||||||
|
unsigned char seqno;
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_GetSlotStatus;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 0; /* RFU */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
set_msg_len (msg, 0);
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, 10);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = bulk_in (handle, msg, sizeof msg, &msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
if (msglen < 10)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n",
|
||||||
|
(unsigned int)msglen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[0] != RDR_to_PC_SlotStatus)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n",
|
||||||
|
msg[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[5] != 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n",
|
||||||
|
msg[5]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[6] != seqno)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n",
|
||||||
|
seqno, msg[6]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr,
|
||||||
|
"ccid-driver: status: %02X error: %02X clock-status: %02X\n",
|
||||||
|
msg[7], msg[8], msg[9] );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
ccid_get_atr (ccid_driver_t handle,
|
||||||
|
unsigned char *atr, size_t maxatrlen, size_t *atrlen)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char msg[100];
|
||||||
|
size_t msglen;
|
||||||
|
unsigned char seqno;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_IccPowerOn;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 0; /* power select (0=auto, 1=5V, 2=3V, 3=1.8V) */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
set_msg_len (msg, 0);
|
||||||
|
msglen = 10;
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = bulk_in (handle, msg, sizeof msg, &msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
if (msglen < 10)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n",
|
||||||
|
(unsigned int)msglen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[0] != RDR_to_PC_DataBlock)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n",
|
||||||
|
msg[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[5] != 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n",
|
||||||
|
msg[5]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[6] != seqno)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n",
|
||||||
|
seqno, msg[6]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr,
|
||||||
|
"ccid-driver: status: %02X error: %02X clock-status: %02X\n"
|
||||||
|
" data:", msg[7], msg[8], msg[9] );
|
||||||
|
for (i=10; i < msglen; i++)
|
||||||
|
fprintf (stderr, " %02X", msg[i]);
|
||||||
|
putc ('\n', stderr);
|
||||||
|
|
||||||
|
if (atr)
|
||||||
|
{
|
||||||
|
size_t n = msglen - 10;
|
||||||
|
|
||||||
|
if (n > maxatrlen)
|
||||||
|
n = maxatrlen;
|
||||||
|
memcpy (atr, msg+10, n);
|
||||||
|
*atrlen = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Protocol T=1 overview
|
||||||
|
|
||||||
|
Block Structure:
|
||||||
|
Prologue Field:
|
||||||
|
1 byte Node Address (NAD)
|
||||||
|
1 byte Protocol Control Byte (PCB)
|
||||||
|
1 byte Length (LEN)
|
||||||
|
Information Field:
|
||||||
|
0-254 byte APDU or Control Information (INF)
|
||||||
|
Epilogue Field:
|
||||||
|
1 byte Error Detection Code (EDC)
|
||||||
|
|
||||||
|
NAD:
|
||||||
|
bit 7 unused
|
||||||
|
bit 4..6 Destination Node Address (DAD)
|
||||||
|
bit 3 unused
|
||||||
|
bit 2..0 Source Node Address (SAD)
|
||||||
|
|
||||||
|
If node adresses are not used, SAD and DAD should be set to 0 on
|
||||||
|
the first block sent to the card. If they are used they should
|
||||||
|
have different values (0 for one is okay); that first block sets up
|
||||||
|
the addresses of the node.
|
||||||
|
|
||||||
|
PCB:
|
||||||
|
Information Block (I-Block):
|
||||||
|
bit 7 0
|
||||||
|
bit 6 Sequence number (yep, that is modulo 2)
|
||||||
|
bit 5 Chaining flag
|
||||||
|
bit 4..0 reserved
|
||||||
|
Received-Ready Block (R-Block):
|
||||||
|
bit 7 1
|
||||||
|
bit 6 0
|
||||||
|
bit 5 0
|
||||||
|
bit 4 Sequence number
|
||||||
|
bit 3..0 0 = no error
|
||||||
|
1 = EDC or parity error
|
||||||
|
2 = other error
|
||||||
|
other values are reserved
|
||||||
|
Supervisory Block (S-Block):
|
||||||
|
bit 7 1
|
||||||
|
bit 6 1
|
||||||
|
bit 5 clear=request,set=response
|
||||||
|
bit 4..0 0 = resyncronisation request
|
||||||
|
1 = information field size request
|
||||||
|
2 = abort request
|
||||||
|
3 = extension of BWT request
|
||||||
|
4 = VPP error
|
||||||
|
other values are reserved
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
ccid_transceive (ccid_driver_t handle,
|
||||||
|
const unsigned char *apdu, size_t apdulen,
|
||||||
|
unsigned char *resp, size_t maxresplen, size_t *nresp)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char msg[10+258], *tpdu, *p;
|
||||||
|
size_t msglen;
|
||||||
|
unsigned char seqno;
|
||||||
|
int i;
|
||||||
|
unsigned char crc;
|
||||||
|
|
||||||
|
|
||||||
|
/* Construct an I-Block. */
|
||||||
|
if (apdulen > 254)
|
||||||
|
return -1; /* Invalid length. */
|
||||||
|
|
||||||
|
tpdu = msg+10;
|
||||||
|
tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */
|
||||||
|
tpdu[1] = ((handle->t1_seqno & 1) << 6); /* I-block */
|
||||||
|
tpdu[2] = apdulen;
|
||||||
|
memcpy (tpdu+3, apdu, apdulen);
|
||||||
|
crc = 0;
|
||||||
|
for (i=0,p=tpdu; i < apdulen+3; i++)
|
||||||
|
crc ^= *p++;
|
||||||
|
tpdu[3+apdulen] = crc;
|
||||||
|
|
||||||
|
handle->t1_seqno ^= 1;
|
||||||
|
|
||||||
|
msg[0] = PC_to_RDR_XfrBlock;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 4; /* bBWI */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
set_msg_len (msg, apdulen+4);
|
||||||
|
msglen = 10 + apdulen + 4;
|
||||||
|
|
||||||
|
fprintf (stderr, "ccid-driver: sending");
|
||||||
|
for (i=0; i < msglen; i++)
|
||||||
|
fprintf (stderr, " %02X", msg[i]);
|
||||||
|
putc ('\n', stderr);
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
rc = bulk_in (handle, msg, sizeof msg, &msglen);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
if (msglen < 10)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n",
|
||||||
|
(unsigned int)msglen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[0] != RDR_to_PC_DataBlock)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n",
|
||||||
|
msg[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[5] != 0)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n",
|
||||||
|
msg[5]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg[6] != seqno)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n",
|
||||||
|
seqno, msg[6]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr,
|
||||||
|
"ccid-driver: status: %02X error: %02X clock-status: %02X\n"
|
||||||
|
" data:", msg[7], msg[8], msg[9] );
|
||||||
|
for (i=10; i < msglen; i++)
|
||||||
|
fprintf (stderr, " %02X", msg[i]);
|
||||||
|
putc ('\n', stderr);
|
||||||
|
|
||||||
|
if (resp)
|
||||||
|
{
|
||||||
|
size_t n = msglen - 10;
|
||||||
|
|
||||||
|
if (n < 4)
|
||||||
|
n = 0; /* fixme: this is an empty I-block or some other block
|
||||||
|
- we ignore it for now until we have implemented the
|
||||||
|
T=1 machinery. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = msg + 10 + 3; /* Skip ccid header and prologue field. */
|
||||||
|
n -= 3;
|
||||||
|
n--; /* Strip the epilogue field. */
|
||||||
|
if (n > maxresplen)
|
||||||
|
n = maxresplen; /* fixme: return an error instead of truncating. */
|
||||||
|
memcpy (resp, p, n);
|
||||||
|
}
|
||||||
|
*nresp = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
ccid_driver_t ccid;
|
||||||
|
|
||||||
|
rc = ccid_open_reader (&ccid, 0);
|
||||||
|
if (rc)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ccid_poll (ccid);
|
||||||
|
fputs ("getting ATR ...\n", stderr);
|
||||||
|
rc = ccid_get_atr (ccid, NULL, 0, NULL);
|
||||||
|
if (rc)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ccid_poll (ccid);
|
||||||
|
fputs ("getting slot status ...\n", stderr);
|
||||||
|
rc = ccid_slot_status (ccid);
|
||||||
|
if (rc)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ccid_poll (ccid);
|
||||||
|
|
||||||
|
{
|
||||||
|
static unsigned char apdu[] = {
|
||||||
|
0, 0xA4, 4, 0, 6, 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01};
|
||||||
|
rc = ccid_transceive (ccid,
|
||||||
|
apdu, sizeof apdu,
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
ccid_poll (ccid);
|
||||||
|
|
||||||
|
{
|
||||||
|
static unsigned char apdu[] = {
|
||||||
|
0, 0xCA, 0, 0x65, 254 };
|
||||||
|
rc = ccid_transceive (ccid,
|
||||||
|
apdu, sizeof apdu,
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
ccid_poll (ccid);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Variables:
|
||||||
|
* compile-command: "gcc -DTEST -Wall -I/usr/local/include -lusb -g ccid-driver.c"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
#endif /*TEST*/
|
||||||
|
#endif /*HAVE_LIBUSB*/
|
40
scd/ccid-driver.h
Normal file
40
scd/ccid-driver.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
|
||||||
|
* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CCID_DRIVER_H
|
||||||
|
#define CCID_DRIVER_H
|
||||||
|
|
||||||
|
|
||||||
|
struct ccid_driver_s;
|
||||||
|
typedef struct ccid_driver_s *ccid_driver_t;
|
||||||
|
|
||||||
|
int ccid_open_reader (ccid_driver_t *handle, int readerno);
|
||||||
|
int ccid_get_atr (ccid_driver_t handle,
|
||||||
|
unsigned char *atr, size_t maxatrlen, size_t *atrlen);
|
||||||
|
int ccid_transceive (ccid_driver_t handle,
|
||||||
|
const unsigned char *apdu, size_t apdulen,
|
||||||
|
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*CCID_DRIVER_H*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -71,6 +71,7 @@ enum cmd_and_opt_values
|
|||||||
oReaderPort,
|
oReaderPort,
|
||||||
octapiDriver,
|
octapiDriver,
|
||||||
opcscDriver,
|
opcscDriver,
|
||||||
|
oDisableCCID,
|
||||||
oDisableOpenSC,
|
oDisableOpenSC,
|
||||||
|
|
||||||
aTest };
|
aTest };
|
||||||
@ -97,9 +98,16 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")},
|
{ oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")},
|
||||||
{ octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")},
|
{ octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")},
|
||||||
{ opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")},
|
{ opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")},
|
||||||
|
{ oDisableCCID, "disable-ccidc", 0,
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
N_("do not use the internal CCID driver")
|
||||||
|
#else
|
||||||
|
"@"
|
||||||
|
#endif
|
||||||
|
/* end --disable-ccid */},
|
||||||
{ oDisableOpenSC, "disable-opensc", 0,
|
{ oDisableOpenSC, "disable-opensc", 0,
|
||||||
#ifdef HAVE_OPENSC
|
#ifdef HAVE_OPENSC
|
||||||
N_("Do not use the OpenSC layer")
|
N_("do not use the OpenSC layer")
|
||||||
#else
|
#else
|
||||||
"@"
|
"@"
|
||||||
#endif
|
#endif
|
||||||
@ -387,6 +395,7 @@ main (int argc, char **argv )
|
|||||||
case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break;
|
case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break;
|
||||||
case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
|
case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
|
||||||
case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
|
case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
|
||||||
|
case oDisableCCID: opt.disable_ccid = 1; break;
|
||||||
case oDisableOpenSC: opt.disable_opensc = 1; break;
|
case oDisableOpenSC: opt.disable_opensc = 1; break;
|
||||||
|
|
||||||
default : pargs.err = configfp? 1:2; break;
|
default : pargs.err = configfp? 1:2; break;
|
||||||
|
@ -55,7 +55,8 @@ struct {
|
|||||||
const char *homedir; /* configuration directory name */
|
const char *homedir; /* configuration directory name */
|
||||||
const char *ctapi_driver; /* Library to access the ctAPI. */
|
const char *ctapi_driver; /* Library to access the ctAPI. */
|
||||||
const char *pcsc_driver; /* Library to access the PC/SC system. */
|
const char *pcsc_driver; /* Library to access the PC/SC system. */
|
||||||
int disable_opensc; /* Disable the sue of the OpenSC framework. */
|
int disable_opensc; /* Disable the use of the OpenSC framework. */
|
||||||
|
int disable_ccid; /* Disable the use of the internal CCID driver. */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user