- Remove all references to usbtoken, use OpenCT instead
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1639 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
b6796d0404
commit
d12b21f633
14
configure.in
14
configure.in
|
@ -526,18 +526,6 @@ else
|
||||||
CFLAGS_PCSC=""
|
CFLAGS_PCSC=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl --enable-usbtoken option.
|
|
||||||
AC_ARG_ENABLE(usbtoken, AC_HELP_STRING(
|
|
||||||
[--enable-usbtoken], [enable the usbtoken reader backed. [default=no]]),
|
|
||||||
, enable_usbtoken=no)
|
|
||||||
if test "x$enable_usbtoken" = "xyes"; then
|
|
||||||
AC_DEFINE(HAVE_USBTOKEN, 1, [Enable usbtoken support])
|
|
||||||
USBTOKEN_MSG=yes
|
|
||||||
else
|
|
||||||
USBTOKEN_MSG=no
|
|
||||||
fi
|
|
||||||
AM_CONDITIONAL(HAVE_USBTOKEN, test "x$USBTOKEN_MSG" = "xyes")
|
|
||||||
|
|
||||||
OPENCT_MSG=no
|
OPENCT_MSG=no
|
||||||
openct_path=/usr
|
openct_path=/usr
|
||||||
AC_SUBST(OPENCT_CFLAGS)
|
AC_SUBST(OPENCT_CFLAGS)
|
||||||
|
@ -868,7 +856,6 @@ src/sslengines/Makefile
|
||||||
src/tests/Makefile
|
src/tests/Makefile
|
||||||
src/tests/regression/Makefile
|
src/tests/regression/Makefile
|
||||||
src/tools/Makefile
|
src/tools/Makefile
|
||||||
src/usbtoken/Makefile
|
|
||||||
win32/Makefile
|
win32/Makefile
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -910,7 +897,6 @@ echo "Random number collection: ${RAND_MSG}"
|
||||||
echo "OpenSSL support: ${SSL_MSG}"
|
echo "OpenSSL support: ${SSL_MSG}"
|
||||||
echo " with engine: ${ENGINE_MSG}"
|
echo " with engine: ${ENGINE_MSG}"
|
||||||
echo "PC/SC support: ${PCSC_MSG}"
|
echo "PC/SC support: ${PCSC_MSG}"
|
||||||
echo "USBToken support: ${USBTOKEN_MSG}"
|
|
||||||
echo "OpenCT support: ${OPENCT_MSG}"
|
echo "OpenCT support: ${OPENCT_MSG}"
|
||||||
echo "Assuan support: ${ASSUAN_MSG}"
|
echo "Assuan support: ${ASSUAN_MSG}"
|
||||||
echo "LDAP support: ${LDAP_MSG}"
|
echo "LDAP support: ${LDAP_MSG}"
|
||||||
|
|
|
@ -24,4 +24,3 @@ Makefile.in
|
||||||
core
|
core
|
||||||
gmon.out
|
gmon.out
|
||||||
pkcs15-profile.5
|
pkcs15-profile.5
|
||||||
usbtoken.html
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Process this file with automake to create Makefile.in
|
# Process this file with automake to create Makefile.in
|
||||||
|
|
||||||
XSLTPROC = @XSLTPROC@
|
XSLTPROC = @XSLTPROC@
|
||||||
HTMLFILES = usbtoken.html opensc.html opensc.css
|
HTMLFILES = opensc.html opensc.css
|
||||||
XMLFILES = usbtoken.xml opensc.xml opensc.xsl
|
XMLFILES = opensc.xml opensc.xsl
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in pkcs15-profile.5
|
MAINTAINERCLEANFILES = Makefile.in pkcs15-profile.5
|
||||||
|
|
||||||
|
|
|
@ -964,52 +964,6 @@
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
<p>
|
|
||||||
Usbtoken is a small driver for usb crypto devices only.
|
|
||||||
It does not need any other helper software and is
|
|
||||||
included in OpenSC for convenience. However Usbtoken is
|
|
||||||
deprecated, the new OpenCT software is now the
|
|
||||||
recommended way to access usb crypto tokens. Usbtoken
|
|
||||||
is no longer actively developed, but bugs are still
|
|
||||||
fixed and help is provided on the OpenSC mailing list
|
|
||||||
at
|
|
||||||
|
|
||||||
<tt class="email">
|
|
||||||
<
|
|
||||||
|
|
||||||
<a href="mailto:opensc-devel@opensc.org">
|
|
||||||
opensc-devel@opensc.org
|
|
||||||
</a>>
|
|
||||||
</tt>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If you still want to use OpenSC with Usbtoken, please
|
|
||||||
configure OpenSC like this:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
$ cd opensc-<version>
|
|
||||||
$ ./configure --enable-usbtoken
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p></p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Documentation on Usbtoken is in the file
|
|
||||||
|
|
||||||
<a href="usbtoken.html" target="_top">
|
|
||||||
usbtoken.html
|
|
||||||
</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
CT-API is a standard format for drivers for smart card
|
CT-API is a standard format for drivers for smart card
|
||||||
readers. It was invented in the eighties for DOS
|
readers. It was invented in the eighties for DOS
|
||||||
|
|
|
@ -343,33 +343,6 @@ $ ./configure --with-openct=/path/to/openct
|
||||||
</screen>
|
</screen>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
Usbtoken is a small driver for usb crypto
|
|
||||||
devices only. It does not need any other helper
|
|
||||||
software and is included in OpenSC for
|
|
||||||
convenience. However Usbtoken is deprecated,
|
|
||||||
the new OpenCT software is now the recommended
|
|
||||||
way to access usb crypto tokens. Usbtoken
|
|
||||||
is no longer actively developed, but bugs are
|
|
||||||
still fixed and help is provided on the
|
|
||||||
OpenSC mailing list at
|
|
||||||
<email>opensc-devel@opensc.org</email>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If you still want to use OpenSC with Usbtoken,
|
|
||||||
please configure OpenSC like this:
|
|
||||||
<screen>
|
|
||||||
$ cd opensc-<version>
|
|
||||||
$ ./configure --enable-usbtoken
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Documentation on Usbtoken is in the file
|
|
||||||
<ulink url="usbtoken.html" />.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
CT-API is a standard format for
|
CT-API is a standard format for
|
||||||
drivers for smart card readers. It was
|
drivers for smart card readers. It was
|
||||||
|
|
|
@ -1,475 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type"
|
|
||||||
content="text/html; charset=UTF-8" />
|
|
||||||
<title>Driver for USB Crypto Token</title>
|
|
||||||
<link rel="stylesheet" href="opensc.css" type="text/css" />
|
|
||||||
<meta name="generator"
|
|
||||||
content="DocBook XSL Stylesheets V1.60.1" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="article" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h1 class="title">
|
|
||||||
<a id="id2799405"></a>Driver for USB Crypto Token</h1>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="author">
|
|
||||||
<h3 class="author">
|
|
||||||
<span class="firstname">Andreas</span>
|
|
||||||
<span class="surname">Jellinghaus</span>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
<hr />
|
|
||||||
</div>
|
|
||||||
<div class="toc">
|
|
||||||
<p>
|
|
||||||
<b>Table of Contents</b>
|
|
||||||
</p>
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2799452">About usbtoken</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2799883">Status</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2799935">Compatibility</a>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
<dl>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2799997">Compatibility List</a>
|
|
||||||
</dt>
|
|
||||||
</dl>
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800018">Requirements</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800062">Compiling OpenSC with USBtoken
|
|
||||||
support</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800076">Installation without hotplug
|
|
||||||
utils</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800125">Installation with hotplut
|
|
||||||
utils</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800184">Security</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800210">Debugging</a>
|
|
||||||
</dt>
|
|
||||||
<dt>
|
|
||||||
<a href="#id2800262">Porting</a>
|
|
||||||
</dt>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
<div class="warning"
|
|
||||||
style="margin-left: 0.5in; margin-right: 0.5in;">
|
|
||||||
<h3 class="title">Warning</h3>Usbtoken is obsolete. Please
|
|
||||||
use OpenCT, a new and much improved smartcard framework. You
|
|
||||||
can download OpenCT from
|
|
||||||
<a href="http://www.opensc.org/files/snapshots"
|
|
||||||
target="_top">http://www.opensc.org/files/snapshots</a></div>
|
|
||||||
<p>If you still want to use ustoken, you need to enable it
|
|
||||||
while configureing OpenSC. For example
|
|
||||||
<tt class="prompt">./configure --enable-usbtok</tt></p>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2799452"></a>About usbtoken</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>This project implements a way for OpenSC to access usb
|
|
||||||
crypto tokens such as:</p>
|
|
||||||
<div class="orderedlist">
|
|
||||||
<ol type="1">
|
|
||||||
<li>Aladdin eToken PRO</li>
|
|
||||||
<li>Rainbow iKey 2032</li>
|
|
||||||
<li>Rainbow iKey 3000</li>
|
|
||||||
<li>Entron CryptoIdentity</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
<p>This project is the successor of the etoken project
|
|
||||||
which created an PC/SC ifdhandler for the Aladdin eToken
|
|
||||||
PRO. Interfacing directly with OpenSC is much easier than
|
|
||||||
using one of the old but well known interfaces like CT-API
|
|
||||||
or PC/SC.</p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2799883"></a>Status</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>The Aladdin eToken PRO works fine. Beware: versions
|
|
||||||
older than 4.1.57 or so might have a problem with USB
|
|
||||||
controllers found on mainboards with VIA chipsets or any
|
|
||||||
uhci based USB controllers. I don't know the details.</p>
|
|
||||||
<p>The Eutron CryptoIdentity IT-Sec works fine.</p>
|
|
||||||
<p>The Eutron CryptoIdentity blue/grey has a smart card
|
|
||||||
operating system by Algorithmic Research. Documentation is
|
|
||||||
only available under a NDA. I'm to busy to sign it and
|
|
||||||
implement support for their driver right now. The usb layer
|
|
||||||
works fine, but I don't know the commands i could send or
|
|
||||||
how a valid response would look like.</p>
|
|
||||||
<p>The Rainbow iKey 2032 has a smart card operating system
|
|
||||||
by DataKey. Documentation is only available under a NDA:
|
|
||||||
I'm to busy to sign it and implement support for their
|
|
||||||
driver right now. The usb layer is supposed to work fine,
|
|
||||||
but I cannot test that without knowing the commands and
|
|
||||||
responses.</p>
|
|
||||||
<p>The Rainbow iKey 3000 has a smart card operating system
|
|
||||||
by Gersike and Devrient called StarCos SPK 2.3. The usb
|
|
||||||
layer is supposed to work fine, but not tested. Further
|
|
||||||
work on the card driver in OpenSC and pkcs11 and pkcs15
|
|
||||||
framework is currently done, please be patient.</p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2799935"></a>Compatibility</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>PKCS#11 is an API standard. It allowes applications to
|
|
||||||
use any library that implements PKCS#11 without changeing
|
|
||||||
code.</p>
|
|
||||||
<p>PKCS#15 is a standard that describes how a PKCS#11
|
|
||||||
library should work. Smartcards have a filesystem, and
|
|
||||||
PKCS#15 makes sure every PCKS#11 library saves data in the
|
|
||||||
right directory, and reads from the right directory.</p>
|
|
||||||
<p>OpenSC offers library implementing the PKCS#11 API
|
|
||||||
according to the PKCS#15 standard. Compatibility has been
|
|
||||||
tested with cards that contain data according to PKCS#15
|
|
||||||
like the finish and swedish ID card.</p>
|
|
||||||
<p>However even if OpenSC can use the usbtoken driver to
|
|
||||||
access a smartcard in a usb token, it will only look in
|
|
||||||
directories where the certificates should be according to
|
|
||||||
PKCS#15.</p>
|
|
||||||
<p>Problem is: most vendors do not install the certificates
|
|
||||||
and keys in the right place, they do not implement PKCS#15
|
|
||||||
in their drivers and libraries.</p>
|
|
||||||
<p>The result is this: you can create a PKCS#15 structure
|
|
||||||
under linux, can put certifiactes and keys and data in it,
|
|
||||||
but when using the vendors drivers you will not see it.
|
|
||||||
Also if you use the vendors driver to store keys,
|
|
||||||
certificates and data, OpenSC will not see it.</p>
|
|
||||||
<p>Using OpenSC on Windows and Linux could solve the
|
|
||||||
situation, but I have no experience with OpenSC under
|
|
||||||
Windows, sorry.</p>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h3 class="title">
|
|
||||||
<a id="id2799997"></a>Compatibility List</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>Aladdin: Their Windows and Unix drivers store keys and
|
|
||||||
certificates in the wrong place. (not compatible with
|
|
||||||
PKCS#15)</p>
|
|
||||||
<p>Eutron: Their Windows and Unix drivers store keys and
|
|
||||||
certificates in the wron place. (not compatible with
|
|
||||||
PKCS#15)</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800018"></a>Requirements</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>Currently the usbtoken only works with linux (kernel
|
|
||||||
2.4.* series and kernel 2.5.* series were tested), but
|
|
||||||
ports to other operating systems should be possible. If you
|
|
||||||
want to port usbtoken, please contact: Andreas Jellinghaus
|
|
||||||
<tt class="email"><
|
|
||||||
<a href="mailto:aj@dungeon.inka.de">
|
|
||||||
aj@dungeon.inka.de</a>></tt></p>
|
|
||||||
<p>You need a kernel compiled with CONFIG_HOTPLUG and
|
|
||||||
CONFIG_USB_DEVICEFS, and the usb device filesystem must be
|
|
||||||
mounted to
|
|
||||||
<tt class="filename">/proc/bus/usb</tt>. And of course
|
|
||||||
kernel support for your usb hub.</p>
|
|
||||||
<p>I guess any linux distribution with kernel 2.4 will be
|
|
||||||
allright and require no changes.</p>
|
|
||||||
<p>Users of other operating systems, please see the porting
|
|
||||||
section.</p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800062"></a>Compiling OpenSC with USBtoken
|
|
||||||
support</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>Call configure with --enable-usbtoken and it compile ok.
|
|
||||||
No special libraries or stuff needed.</p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800076"></a>Installation without hotplug
|
|
||||||
utils</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<b class="command">ls /sbin/hotplug</b>
|
|
||||||
</p>
|
|
||||||
<p>If there is no such file, the installation is very
|
|
||||||
easy:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
ln -s /path/to/opensc/sbin/usbtoken /sbin/hotplug
|
|
||||||
mkdir /var/run/usbtoken
|
|
||||||
chmod 755 /var/run/usbtoken
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
<p>Now attach some usb token. The kernel will start
|
|
||||||
<tt class="filename">/sbin/hotplug</tt>, and you can see
|
|
||||||
some usbtoken running as daemon: you will find a pid file
|
|
||||||
in
|
|
||||||
<tt class="filename">/var/run</tt>and a socket in
|
|
||||||
<tt class="filename">/var/run/usbtoken/</tt>.</p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800125"></a>Installation with hotplut
|
|
||||||
utils</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>First the general instructions, then the debian specific
|
|
||||||
instructions. As usual debian does everything a bit
|
|
||||||
different. That doesn't mean it is necessarily better or
|
|
||||||
worse.</p>
|
|
||||||
<p>Edit
|
|
||||||
<tt class="filename">/etc/hotplug/usb.usermap</tt>and add
|
|
||||||
these lines:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
usbtoken 0x0003 0x0529 0x050c 0x0000 0x0001 0xff 0x00 0x00 0xff
|
|
||||||
0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x0529 0x0514 0x0000 0x0001 0xff 0x00 0x00 0xff
|
|
||||||
0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x04b9 0x1202 0x0000 0x0001 0xff 0x00 0x00 0xff
|
|
||||||
0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x04b9 0x1300 0x0000 0x0001 0xff 0x00 0x00 0xff
|
|
||||||
0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x073d 0x0005 0x0020 0x0001 0xff 0x00 0x00 0xff
|
|
||||||
0x00 0x00 0x00000000
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
<p>Create the directory
|
|
||||||
<tt class="filename">/etc/hotplug/usb</tt>and add a symlink
|
|
||||||
to usbtoken. Also create the directory
|
|
||||||
<tt class="filename">/var/run/usbtoken</tt>and set
|
|
||||||
permissions to 0755 (everyone can access that
|
|
||||||
directory):</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
ln -s /path/to/opensc/sbin/usbtoken /etc/hotplug/usb/
|
|
||||||
mkdir /var/run/usbtoken
|
|
||||||
chmod 0755 /var/run/usbtoken
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800184"></a>Security</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>By default everyone can use the usbtokens. If you want
|
|
||||||
to limit this to a certain user:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
chown user /var/run/usbtoken/
|
|
||||||
chmod 0700 /var/run/usbtoken/
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>Or if you want to limit this to a certain group:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
chgrp group /var/run/usbtoken/
|
|
||||||
chmod 0750 /var/run/usbtoken/
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800210"></a>Debugging</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>TODO: send me problem reports and I will add advice
|
|
||||||
here.</p>
|
|
||||||
<p>Edit src/usbtoken/Makefile and Makefile.in and add
|
|
||||||
"-DUSB_DEBUG" to CFLAGS. make clean, make, make install.
|
|
||||||
Now it will dump all usb traffic to syslog. I should be
|
|
||||||
able to understand what is going wrong based on that log
|
|
||||||
file.</p>
|
|
||||||
<p>For development I use a special crafted
|
|
||||||
<tt class="filename">/sbin/hotplug</tt>shell script that
|
|
||||||
creates another script
|
|
||||||
<tt class="filename">/root/sim</tt>whis I invoke in an
|
|
||||||
xterm. That script spawns gdb so I can debug the whole
|
|
||||||
process. In gdb I usualy set a breakpoint, and run the
|
|
||||||
command with
|
|
||||||
<b class="command">r usb</b>. My hotplug script:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -n "$PRODUCT" ]
|
|
||||||
then
|
|
||||||
if [ "$ACTION" = "add" ]
|
|
||||||
then
|
|
||||||
export > /root/sim
|
|
||||||
echo "echo $*" >> /root/sim
|
|
||||||
echo gdb /home/aj/opensc/sbin/usbtoken >>
|
|
||||||
/root/sim
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
</div>
|
|
||||||
<div class="section" lang="en" xml:lang="en">
|
|
||||||
<div class="titlepage">
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<h2 class="title" style="clear: both">
|
|
||||||
<a id="id2800262"></a>Porting</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
<p>To port usbtoken mainly
|
|
||||||
<tt class="filename">usb.c</tt>needs some changes. The core
|
|
||||||
sequence for linux is:</p>
|
|
||||||
<table border="0" bgcolor="#E0E0E0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<pre class="screen">
|
|
||||||
|
|
||||||
#include <linux/usbdevice_fs.h>
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
struct usbdevfs_ctrltransfer ctrl;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
ctrl.requesttype = type;
|
|
||||||
ctrl.request = req;
|
|
||||||
ctrl.value = value;
|
|
||||||
ctrl.index = index;
|
|
||||||
ctrl.length = size;
|
|
||||||
ctrl.data = buf;
|
|
||||||
ctrl.timeout = 10000;
|
|
||||||
rc = ioctl(usbtoken.usbfd, USBDEVFS_CONTROL, &ctrl);
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>rc now has the error (-1/errno/strerror) or the number
|
|
||||||
of bytes read/written on success. Change it to suit your
|
|
||||||
OS, or let me know how to do it, and usb should work.</p>
|
|
||||||
<p>Usbtoken also needs an usb device filesystem or some
|
|
||||||
device it can open and use with I/O controls. That should
|
|
||||||
be available with every OS.</p>
|
|
||||||
<p>Finaly usbtoken depends to be called by some hotplug
|
|
||||||
mechanism. Under linux the kernel executes
|
|
||||||
<tt class="filename">/sbin/hotplug</tt>everytime a device
|
|
||||||
is added (or removed, but I don't use that). If your OS has
|
|
||||||
no such service, you can write a daemon that somehow finds
|
|
||||||
out when a device is added and start usbtoken with the
|
|
||||||
required environment settings.</p>
|
|
||||||
<p>Windows? Ugh. I have no idea about windows, what we can
|
|
||||||
do, how it works, etc. Volunteers welcome.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,390 +0,0 @@
|
||||||
<?xml version="1.0" encoding="iso8859-1" ?>
|
|
||||||
<article ns="http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
|
|
||||||
<articleinfo>
|
|
||||||
<author>
|
|
||||||
<firstname>Andreas</firstname>
|
|
||||||
<surname>Jellinghaus</surname>
|
|
||||||
</author>
|
|
||||||
<title>Driver for USB Crypto Token</title>
|
|
||||||
</articleinfo>
|
|
||||||
|
|
||||||
<warning>
|
|
||||||
Usbtoken is obsolete. Please use OpenCT, a new and
|
|
||||||
much improved smartcard framework. You can download
|
|
||||||
OpenCT from
|
|
||||||
<ulink url="http://www.opensc.org/files/snapshots" />
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If you still want to use ustoken, you need to enable it
|
|
||||||
while configureing OpenSC. For example
|
|
||||||
<prompt>./configure --enable-usbtoken</prompt>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<toc></toc>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>About usbtoken</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This project implements a way for OpenSC to access
|
|
||||||
usb crypto tokens such as:
|
|
||||||
</para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>Aladdin eToken PRO</listitem>
|
|
||||||
<listitem>Rainbow iKey 2032</listitem>
|
|
||||||
<listitem>Rainbow iKey 3000</listitem>
|
|
||||||
<listitem>Entron CryptoIdentity</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This project is the successor of the etoken
|
|
||||||
project which created an PC/SC ifdhandler for the
|
|
||||||
Aladdin eToken PRO. Interfacing directly with
|
|
||||||
OpenSC is much easier than using one of the
|
|
||||||
old but well known interfaces like CT-API or PC/SC.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Status</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Aladdin eToken PRO works fine.
|
|
||||||
Beware: versions older than 4.1.57 or so
|
|
||||||
might have a problem with USB controllers
|
|
||||||
found on mainboards with VIA chipsets
|
|
||||||
or any uhci based USB controllers.
|
|
||||||
I don't know the details.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Eutron CryptoIdentity IT-Sec works fine.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Eutron CryptoIdentity blue/grey has a
|
|
||||||
smart card operating system by Algorithmic
|
|
||||||
Research. Documentation is only available
|
|
||||||
under a NDA. I'm to busy to sign it and
|
|
||||||
implement support for their driver right now.
|
|
||||||
The usb layer works fine, but I don't know
|
|
||||||
the commands i could send or how a valid
|
|
||||||
response would look like.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Rainbow iKey 2032 has a smart card operating
|
|
||||||
system by DataKey. Documentation is only available
|
|
||||||
under a NDA: I'm to busy to sign it and
|
|
||||||
implement support for their driver right now.
|
|
||||||
The usb layer is supposed to work fine,
|
|
||||||
but I cannot test that without knowing
|
|
||||||
the commands and responses.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Rainbow iKey 3000 has a smart card operating
|
|
||||||
system by Gersike and Devrient called StarCos
|
|
||||||
SPK 2.3. The usb layer is supposed to work fine,
|
|
||||||
but not tested. Further work on the card driver
|
|
||||||
in OpenSC and pkcs11 and pkcs15 framework
|
|
||||||
is currently done, please be patient.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Compatibility</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
PKCS#11 is an API standard. It allowes applications
|
|
||||||
to use any library that implements PKCS#11 without
|
|
||||||
changeing code.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
PKCS#15 is a standard that describes how a PKCS#11
|
|
||||||
library should work. Smartcards have a filesystem,
|
|
||||||
and PKCS#15 makes sure every PCKS#11 library
|
|
||||||
saves data in the right directory, and reads
|
|
||||||
from the right directory.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
OpenSC offers library implementing the PKCS#11 API
|
|
||||||
according to the PKCS#15 standard. Compatibility
|
|
||||||
has been tested with cards that contain data
|
|
||||||
according to PKCS#15 like the finish and swedish
|
|
||||||
ID card.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
However even if OpenSC can use the usbtoken driver
|
|
||||||
to access a smartcard in a usb token, it will
|
|
||||||
only look in directories where the certificates
|
|
||||||
should be according to PKCS#15.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Problem is: most vendors do not install the
|
|
||||||
certificates and keys in the right place,
|
|
||||||
they do not implement PKCS#15 in their
|
|
||||||
drivers and libraries.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The result is this: you can create a PKCS#15
|
|
||||||
structure under linux, can put certifiactes
|
|
||||||
and keys and data in it, but when using the
|
|
||||||
vendors drivers you will not see it. Also
|
|
||||||
if you use the vendors driver to store keys,
|
|
||||||
certificates and data, OpenSC will not see it.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Using OpenSC on Windows and Linux could solve
|
|
||||||
the situation, but I have no experience with
|
|
||||||
OpenSC under Windows, sorry.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Compatibility List</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Aladdin: Their Windows and Unix drivers store
|
|
||||||
keys and certificates in the wrong place.
|
|
||||||
(not compatible with PKCS#15)
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Eutron: Their Windows and Unix drivers store
|
|
||||||
keys and certificates in the wron place.
|
|
||||||
(not compatible with PKCS#15)
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Requirements</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Currently the usbtoken only works with linux
|
|
||||||
(kernel 2.4.* series and kernel 2.5.* series
|
|
||||||
were tested), but ports to other operating
|
|
||||||
systems should be possible. If you want to
|
|
||||||
port usbtoken, please contact: Andreas Jellinghaus
|
|
||||||
<email>aj@dungeon.inka.de</email>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You need a kernel compiled with CONFIG_HOTPLUG
|
|
||||||
and CONFIG_USB_DEVICEFS, and the usb device filesystem
|
|
||||||
must be mounted to <filename>/proc/bus/usb</filename>.
|
|
||||||
And of course kernel support for your usb hub.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
I guess any linux distribution with kernel 2.4
|
|
||||||
will be allright and require no changes.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Users of other operating systems, please see
|
|
||||||
the porting section.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Compiling OpenSC with USBtoken support</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Call configure with --enable-usbtoken and it
|
|
||||||
compile ok. No special libraries or stuff needed.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Installation without hotplug utils</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<command>ls /sbin/hotplug</command>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If there is no such file, the installation
|
|
||||||
is very easy:
|
|
||||||
<screen>
|
|
||||||
ln -s /path/to/opensc/sbin/usbtoken /sbin/hotplug
|
|
||||||
mkdir /var/run/usbtoken
|
|
||||||
chmod 755 /var/run/usbtoken
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now attach some usb token. The kernel will start
|
|
||||||
<filename>/sbin/hotplug</filename>, and you can
|
|
||||||
see some usbtoken running as daemon: you will find
|
|
||||||
a pid file in <filename>/var/run</filename>
|
|
||||||
and a socket in <filename>/var/run/usbtoken/</filename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Installation with hotplut utils</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
First the general instructions, then the debian
|
|
||||||
specific instructions. As usual debian does
|
|
||||||
everything a bit different. That doesn't mean
|
|
||||||
it is necessarily better or worse.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Edit <filename>/etc/hotplug/usb.usermap</filename>
|
|
||||||
and add these lines:
|
|
||||||
<screen>
|
|
||||||
usbtoken 0x0003 0x0529 0x050c 0x0000 0x0001 0xff 0x00 0x00 0xff 0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x0529 0x0514 0x0000 0x0001 0xff 0x00 0x00 0xff 0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x04b9 0x1202 0x0000 0x0001 0xff 0x00 0x00 0xff 0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x04b9 0x1300 0x0000 0x0001 0xff 0x00 0x00 0xff 0x00 0x00 0x00000000
|
|
||||||
usbtoken 0x0003 0x073d 0x0005 0x0020 0x0001 0xff 0x00 0x00 0xff 0x00 0x00 0x00000000
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Create the directory
|
|
||||||
<filename>/etc/hotplug/usb</filename> and add a symlink
|
|
||||||
to usbtoken. Also create the directory
|
|
||||||
<filename>/var/run/usbtoken</filename> and set
|
|
||||||
permissions to 0755 (everyone can access that
|
|
||||||
directory):
|
|
||||||
<screen>
|
|
||||||
ln -s /path/to/opensc/sbin/usbtoken /etc/hotplug/usb/
|
|
||||||
mkdir /var/run/usbtoken
|
|
||||||
chmod 0755 /var/run/usbtoken
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Security</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
By default everyone can use the usbtokens. If you want
|
|
||||||
to limit this to a certain user:
|
|
||||||
<screen>
|
|
||||||
chown user /var/run/usbtoken/
|
|
||||||
chmod 0700 /var/run/usbtoken/
|
|
||||||
</screen>
|
|
||||||
Or if you want to limit this to a certain group:
|
|
||||||
<screen>
|
|
||||||
chgrp group /var/run/usbtoken/
|
|
||||||
chmod 0750 /var/run/usbtoken/
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Debugging</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
TODO: send me problem reports and I will add
|
|
||||||
advice here.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Edit src/usbtoken/Makefile and Makefile.in
|
|
||||||
and add "-DUSB_DEBUG" to CFLAGS. make clean,
|
|
||||||
make, make install. Now it will dump
|
|
||||||
all usb traffic to syslog. I should be able
|
|
||||||
to understand what is going wrong based
|
|
||||||
on that log file.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
For development I use a special crafted
|
|
||||||
<filename>/sbin/hotplug</filename> shell script
|
|
||||||
that creates another script
|
|
||||||
<filename>/root/sim</filename> whis I invoke in
|
|
||||||
an xterm. That script spawns gdb so I can
|
|
||||||
debug the whole process. In gdb I usualy
|
|
||||||
set a breakpoint, and run the command with
|
|
||||||
<command>r usb</command>. My hotplug script:
|
|
||||||
<screen>
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -n "$PRODUCT" ]
|
|
||||||
then
|
|
||||||
if [ "$ACTION" = "add" ]
|
|
||||||
then
|
|
||||||
export > /root/sim
|
|
||||||
echo "echo $*" >> /root/sim
|
|
||||||
echo gdb /home/aj/opensc/sbin/usbtoken >> /root/sim
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
</screen>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Porting</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To port usbtoken mainly <filename>usb.c</filename>
|
|
||||||
needs some changes. The core sequence for linux
|
|
||||||
is:
|
|
||||||
<screen><![CDATA[
|
|
||||||
|
|
||||||
#include <linux/usbdevice_fs.h>
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
struct usbdevfs_ctrltransfer ctrl;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
ctrl.requesttype = type;
|
|
||||||
ctrl.request = req;
|
|
||||||
ctrl.value = value;
|
|
||||||
ctrl.index = index;
|
|
||||||
ctrl.length = size;
|
|
||||||
ctrl.data = buf;
|
|
||||||
ctrl.timeout = 10000;
|
|
||||||
rc = ioctl(usbtoken.usbfd, USBDEVFS_CONTROL, &ctrl);
|
|
||||||
|
|
||||||
]]></screen>
|
|
||||||
rc now has the error (-1/errno/strerror) or the
|
|
||||||
number of bytes read/written on success.
|
|
||||||
Change it to suit your OS, or let me know
|
|
||||||
how to do it, and usb should work.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Usbtoken also needs an usb device filesystem
|
|
||||||
or some device it can open and use with I/O controls.
|
|
||||||
That should be available with every OS.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Finaly usbtoken depends to be called by some
|
|
||||||
hotplug mechanism. Under linux the kernel
|
|
||||||
executes <filename>/sbin/hotplug</filename>
|
|
||||||
everytime a device is added (or removed, but
|
|
||||||
I don't use that). If your OS has no such
|
|
||||||
service, you can write a daemon that
|
|
||||||
somehow finds out when a device is added
|
|
||||||
and start usbtoken with the required environment
|
|
||||||
settings.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Windows? Ugh. I have no idea about windows,
|
|
||||||
what we can do, how it works, etc. Volunteers
|
|
||||||
welcome.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</article>
|
|
|
@ -6,4 +6,4 @@ EXTRA_DIST = Makefile.mak
|
||||||
|
|
||||||
# Order IS important
|
# Order IS important
|
||||||
SUBDIRS = common include scconf scdl scldap scrandom libopensc pkcs15init pkcs11 \
|
SUBDIRS = common include scconf scdl scldap scrandom libopensc pkcs15init pkcs11 \
|
||||||
tests tools openscd openssh scam pam sia signer usbtoken sslengines
|
tests tools openscd openssh scam pam sia signer sslengines
|
||||||
|
|
|
@ -22,8 +22,7 @@ libopensc_la_SOURCES = \
|
||||||
\
|
\
|
||||||
emv.c \
|
emv.c \
|
||||||
\
|
\
|
||||||
ctbcs.c reader-ctapi.c reader-pcsc.c \
|
ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c \
|
||||||
reader-openct.c reader-usbtoken.c \
|
|
||||||
\
|
\
|
||||||
card-setcos.c card-miocos.c card-flex.c card-gpk.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-etoken.c card-tcos.c card-emv.c card-default.c \
|
||||||
|
|
|
@ -75,9 +75,6 @@ static const struct _sc_driver_entry internal_reader_drivers[] = {
|
||||||
#ifdef HAVE_OPENCT
|
#ifdef HAVE_OPENCT
|
||||||
{ "openct", (void *) sc_get_openct_driver, NULL },
|
{ "openct", (void *) sc_get_openct_driver, NULL },
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_USBTOKEN
|
|
||||||
{ "usbtoken", (void *) sc_get_usbtoken_driver, NULL },
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -844,7 +844,6 @@ 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_pcsc_driver(void);
|
||||||
extern const struct sc_reader_driver *sc_get_ctapi_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 const struct sc_reader_driver *sc_get_openct_driver(void);
|
extern const struct sc_reader_driver *sc_get_openct_driver(void);
|
||||||
|
|
||||||
extern struct sc_card_driver *sc_get_default_driver(void);
|
extern struct sc_card_driver *sc_get_default_driver(void);
|
||||||
|
|
|
@ -1,351 +0,0 @@
|
||||||
/*
|
|
||||||
* reader-usbtoken.c: Reader driver for USBtoken
|
|
||||||
*
|
|
||||||
* Copyright (C) 2002 Andreas Jellinghaus <aj@dungeon.inka.de>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
#ifdef HAVE_USBTOKEN
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* we will create that many usbtoken readers */
|
|
||||||
#define READERS 5
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
static struct sc_reader_operations usbtoken_ops;
|
|
||||||
|
|
||||||
static struct sc_reader_driver usbtoken_reader_driver = {
|
|
||||||
"USB Crypto Token Reader",
|
|
||||||
"usbtoken",
|
|
||||||
&usbtoken_ops
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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, 4);
|
|
||||||
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_ops;
|
|
||||||
myreader->slot_count = 1;
|
|
||||||
myreader->name = strdup("USB Crypto Token %d");
|
|
||||||
snprintf(myreader->name, strlen(myreader->name),
|
|
||||||
myreader->name, i);
|
|
||||||
myprivslot = malloc(sizeof(struct usbtoken_privslot));
|
|
||||||
bzero(myprivslot, sizeof(struct usbtoken_privslot));
|
|
||||||
myreader->slot[0].drv_data = myprivslot;
|
|
||||||
myreader->slot[0].flags = SC_SLOT_CARD_PRESENT;
|
|
||||||
|
|
||||||
myprivslot->fd = -1;
|
|
||||||
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, 4);
|
|
||||||
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, 4);
|
|
||||||
myprivslot = reader->slot[0].drv_data;
|
|
||||||
if (myprivslot) {
|
|
||||||
if (myprivslot->fd >= 0)
|
|
||||||
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, newflags;
|
|
||||||
|
|
||||||
SC_FUNC_CALLED(reader->ctx, 4);
|
|
||||||
myprivslot = slot->drv_data;
|
|
||||||
|
|
||||||
newflags =
|
|
||||||
slot->flags & ~(SC_SLOT_CARD_PRESENT | SC_SLOT_CARD_CHANGED);
|
|
||||||
|
|
||||||
|
|
||||||
if (myprivslot->fd >= 0) {
|
|
||||||
struct pollfd pfd;
|
|
||||||
pfd.fd = myprivslot->fd;
|
|
||||||
pfd.events = 0;
|
|
||||||
rc = poll(&pfd, 1, 0);
|
|
||||||
if (pfd.revents & POLLHUP) { /* card removed, slot invalid */
|
|
||||||
newflags |= SC_SLOT_CARD_CHANGED;
|
|
||||||
usbtoken_reader_disconnect(reader, slot,
|
|
||||||
SC_DISCONNECT);
|
|
||||||
usbtoken_reader_connect(reader, slot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = stat(myprivslot->sa_un.sun_path, &statbuf);
|
|
||||||
|
|
||||||
if (rc != -1)
|
|
||||||
newflags |= SC_SLOT_CARD_PRESENT;
|
|
||||||
|
|
||||||
if ((slot->flags & SC_SLOT_CARD_PRESENT) != newflags)
|
|
||||||
newflags |= SC_SLOT_CARD_CHANGED;
|
|
||||||
slot->flags = newflags;
|
|
||||||
|
|
||||||
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, 4);
|
|
||||||
myprivslot = slot->drv_data;
|
|
||||||
|
|
||||||
assert(myprivslot->fd >= 0);
|
|
||||||
rc = write(myprivslot->fd, &cmd, sizeof(cmd));
|
|
||||||
if (rc != sizeof(cmd)) {
|
|
||||||
sc_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) {
|
|
||||||
sc_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, 4);
|
|
||||||
myprivslot = slot->drv_data;
|
|
||||||
|
|
||||||
rc = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (rc < 0) {
|
|
||||||
sc_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 = -1;
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_connect: connect(%s) failed\n",
|
|
||||||
myprivslot->sa_un.sun_path);
|
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = read(myprivslot->fd, slot->atr, SC_MAX_ATR_SIZE);
|
|
||||||
if (rc == -1) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_connect: read failed on %s\n",
|
|
||||||
myprivslot->sa_un.sun_path);
|
|
||||||
return SC_ERROR_READER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_connect: read on %s recieved no data\n",
|
|
||||||
myprivslot->sa_un.sun_path);
|
|
||||||
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, 4);
|
|
||||||
myprivslot = slot->drv_data;
|
|
||||||
if (myprivslot->fd >= 0) {
|
|
||||||
close(myprivslot->fd);
|
|
||||||
myprivslot->fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 4);
|
|
||||||
myprivslot = slot->drv_data;
|
|
||||||
|
|
||||||
assert(myprivslot->fd >= 0);
|
|
||||||
if (sendsize > 1023) {
|
|
||||||
sc_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) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_transmit write failed\n");
|
|
||||||
return SC_ERROR_READER;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = read(myprivslot->fd, buffer, sizeof(buffer));
|
|
||||||
if (rc == -1) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_transmit read failed\n");
|
|
||||||
return SC_ERROR_READER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_transmit recved no data\n");
|
|
||||||
return SC_ERROR_READER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] != 3) {
|
|
||||||
sc_error(reader->ctx,
|
|
||||||
"usbtoken_reader_transmit token failed\n");
|
|
||||||
return SC_ERROR_READER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc - 1 > *recvsize) {
|
|
||||||
sc_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, 4);
|
|
||||||
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, 4);
|
|
||||||
return usbtoken_reader_unix_cmd(reader, slot, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct sc_reader_driver *sc_get_usbtoken_driver(void)
|
|
||||||
{
|
|
||||||
usbtoken_ops.init = usbtoken_reader_init;
|
|
||||||
usbtoken_ops.finish = usbtoken_reader_finish;
|
|
||||||
usbtoken_ops.release = usbtoken_reader_release;
|
|
||||||
usbtoken_ops.detect_card_presence = usbtoken_reader_detect_card_presence;
|
|
||||||
usbtoken_ops.connect = usbtoken_reader_connect;
|
|
||||||
usbtoken_ops.disconnect = usbtoken_reader_disconnect;
|
|
||||||
usbtoken_ops.transmit = usbtoken_reader_transmit;
|
|
||||||
usbtoken_ops.lock = usbtoken_reader_lock;
|
|
||||||
usbtoken_ops.unlock = usbtoken_reader_unlock;
|
|
||||||
|
|
||||||
return &usbtoken_reader_driver;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_USBTOKEN */
|
|
|
@ -1,26 +0,0 @@
|
||||||
.deps
|
|
||||||
.libs
|
|
||||||
.#*#
|
|
||||||
.*.bak
|
|
||||||
.*.orig
|
|
||||||
.*.rej
|
|
||||||
.*~
|
|
||||||
#*#
|
|
||||||
*.bak
|
|
||||||
*.d
|
|
||||||
*.def
|
|
||||||
*.dll
|
|
||||||
*.exe
|
|
||||||
*.la
|
|
||||||
*.lib
|
|
||||||
*.lo
|
|
||||||
*.orig
|
|
||||||
*.pdb
|
|
||||||
*.rej
|
|
||||||
*.u
|
|
||||||
*~
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
core
|
|
||||||
gmon.out
|
|
||||||
usbtoken
|
|
|
@ -1,12 +0,0 @@
|
||||||
usbtoken is no longer active developed.
|
|
||||||
Please use openct
|
|
||||||
http://www.opensc.org/files/
|
|
||||||
|
|
||||||
I will support usbtoken for a short while, and
|
|
||||||
fix any bugs reported. But most likely usbtoken
|
|
||||||
will be removed from opensc in 0.9.0. So the
|
|
||||||
sooner you migrate to openct the better.
|
|
||||||
|
|
||||||
Sorry for causing this inconvinience.
|
|
||||||
|
|
||||||
Regards, Andreas
|
|
|
@ -1,12 +0,0 @@
|
||||||
# Process this file with automake to create Makefile.in
|
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
|
||||||
EXTRA_DIST = DEPRECATED
|
|
||||||
|
|
||||||
if HAVE_USBTOKEN
|
|
||||||
sbin_PROGRAMS = usbtoken
|
|
||||||
endif
|
|
||||||
|
|
||||||
usbtoken_SOURCES = atr.c eutron.c etoken.c ikey2k.c ikey3k.c main.c pid.c \
|
|
||||||
socket.c t1.c usb.c usbtoken.h
|
|
||||||
#usbtoken_CFLAGS = -DUSB_DEBUG
|
|
|
@ -1,274 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
int is_atr_complete(uint8_t* buffer, int lr)
|
|
||||||
{
|
|
||||||
int hc, i, td, rc;
|
|
||||||
|
|
||||||
/* TS, T0 and checksum are always required */
|
|
||||||
if (lr < 3)
|
|
||||||
return USBTOKEN_INCOMPLETE;
|
|
||||||
|
|
||||||
if (buffer[0] != 0x3b) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"is_atr_complete fatal: atr not direct convention, TS %d",
|
|
||||||
buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hc = buffer[1] & 0xf;
|
|
||||||
|
|
||||||
/* ok, first round, starting with byte 2, for T=0 */
|
|
||||||
i = 2;
|
|
||||||
td = buffer[1] >> 4;
|
|
||||||
|
|
||||||
while (td) {
|
|
||||||
if (td & 0x01)
|
|
||||||
i++; /* TAn */
|
|
||||||
if (td & 0x02)
|
|
||||||
i++; /* TBn */
|
|
||||||
if (td & 0x04)
|
|
||||||
i++; /* TCn */
|
|
||||||
if (td & 0x08) { /* TDn */
|
|
||||||
if (lr < i)
|
|
||||||
return USBTOKEN_INCOMPLETE;
|
|
||||||
td = buffer[i] >> 4;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
td = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lr < i + hc + 1)
|
|
||||||
return USBTOKEN_INCOMPLETE;
|
|
||||||
|
|
||||||
lr = i + hc + 1;
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (i = 1; i < lr; i++) {
|
|
||||||
rc ^= buffer[i];
|
|
||||||
}
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "is_atr_complete fatal: checksum invalid");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_atr()
|
|
||||||
{
|
|
||||||
int hc, i, td, proto, rc;
|
|
||||||
|
|
||||||
if (usbtoken.atr == 0) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: no ATR received");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.atrlen < 1) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: TS missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.atr[0] != 0x3b) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"parse_atr fatal: atr not direct convention, TS %d",
|
|
||||||
usbtoken.atr[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.atrlen < 2) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: T0 missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hc = usbtoken.atr[1] & 0xf;
|
|
||||||
|
|
||||||
/* ok, first round, starting with byte 2, for T=0 */
|
|
||||||
i = 2;
|
|
||||||
proto = 0;
|
|
||||||
td = usbtoken.atr[1] >> 4;
|
|
||||||
|
|
||||||
if (td & 0x1) { /* TA1 */
|
|
||||||
/* timing stuff, i don't care */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x02) { /* TB1 */
|
|
||||||
/* vpp voltage, obsolete */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x04) { /* TC1 */
|
|
||||||
/* extra guard time, i don't care */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x08) { /* TD1 */
|
|
||||||
if (usbtoken.atrlen < i) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: TD1 missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
td = usbtoken.atr[i] >> 4;
|
|
||||||
proto = usbtoken.atr[i] & 0xf;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
td = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x01) { /* TA2 */
|
|
||||||
/* global interface character, for PTS */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x02) { /* TB2 */
|
|
||||||
/* vpp voltage */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x04) { /* TC2 */
|
|
||||||
/* work waiting time */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x08) { /* TD2 */
|
|
||||||
if (usbtoken.atrlen < i) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: TD2 missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
td = usbtoken.atr[i] >> 4;
|
|
||||||
proto = usbtoken.atr[i] & 0xf;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
td = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (td) {
|
|
||||||
if (td & 0x01) { /* TAn */
|
|
||||||
/* ifsc */
|
|
||||||
if (usbtoken.atrlen < i) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"parse_atr fatal: TAn missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
if (proto == 1) {
|
|
||||||
usbtoken.ifsc = usbtoken.atr[i];
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x02) { /* TBn */
|
|
||||||
/* character waiting time */
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x04) { /* TCn */
|
|
||||||
/* lrc/crc */
|
|
||||||
if (usbtoken.atrlen < i) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"parse_atr fatal: TAn missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
if (proto == 1) {
|
|
||||||
usbtoken.rc = usbtoken.atr[i] & 0x1;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td & 0x08) { /* TDn */
|
|
||||||
if (usbtoken.atrlen < i) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"parse_atr fatal: TDn missing");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
td = usbtoken.atr[i] >> 4;
|
|
||||||
proto = usbtoken.atr[i] & 0xf;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
td = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.atrlen != i + hc + 1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"parse_atr fatal: length should be %d, is %d",
|
|
||||||
i + hc, usbtoken.atrlen);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (i = 1; i < usbtoken.atrlen; i++) {
|
|
||||||
rc ^= usbtoken.atr[i];
|
|
||||||
}
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "parse_atr fatal: checksum invalid");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int increase_ifsc()
|
|
||||||
{
|
|
||||||
uint8_t buf_send[256];
|
|
||||||
uint8_t buf_recv[256];
|
|
||||||
uint8_t max_ifsc;
|
|
||||||
int len_recv, rc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
max_ifsc = usbtoken.ifsc;
|
|
||||||
if (max_ifsc > usbtoken.drv.max_ifsc) {
|
|
||||||
max_ifsc = usbtoken.drv.max_ifsc;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbtoken.ifsc = 0x20;
|
|
||||||
|
|
||||||
if (max_ifsc == 0x20) {
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
};
|
|
||||||
|
|
||||||
buf_send[0] = 0x00;
|
|
||||||
buf_send[1] = 0xc1;
|
|
||||||
buf_send[2] = 0x01;
|
|
||||||
buf_send[3] = max_ifsc;
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
rc ^= buf_send[i];
|
|
||||||
}
|
|
||||||
buf_send[4] = rc;
|
|
||||||
|
|
||||||
len_recv = sizeof(buf_recv);
|
|
||||||
rc = usbtoken.drv.transmit(buf_send, 5, buf_recv, &len_recv);
|
|
||||||
if (rc != USBTOKEN_OK)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
if (len_recv < 5) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"increase_ifsc fatal: expected (at least) 5 byte answer, got %d",
|
|
||||||
len_recv);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (i = 0; i < 4 + buf_recv[2]; i++) {
|
|
||||||
rc ^= buf_recv[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "increase_ifsc fatal: checksum mismatch");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_recv[0] != 0x0 || buf_recv[1] != 0xe1
|
|
||||||
|| buf_recv[2] != 0x01) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"increase_ifsc fatal: did not get ifsc answer");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbtoken.ifsc = buf_recv[3];
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
int etoken_init();
|
|
||||||
int etoken_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv);
|
|
||||||
|
|
||||||
const struct token_drv etoken_drv = {
|
|
||||||
.init = etoken_init,
|
|
||||||
.transmit = etoken_transmit,
|
|
||||||
.max_ifsc = 32, /* higher ifsc causes etoken to crash */
|
|
||||||
.timeout = 10000,
|
|
||||||
.name = "Aladdin eToken PRO",
|
|
||||||
};
|
|
||||||
|
|
||||||
char *etoken_products[] = { "529/50c/100", "529/514/100", 0 };
|
|
||||||
|
|
||||||
int etoken_test(char *product)
|
|
||||||
{
|
|
||||||
char **p;
|
|
||||||
if (!product)
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
|
|
||||||
for (p = etoken_products; *p; p++) {
|
|
||||||
if (strcmp(product, *p) == 0) {
|
|
||||||
usbtoken.drv = etoken_drv;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int etoken_init()
|
|
||||||
{
|
|
||||||
int rc, len;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
uint8_t cookie[] = { 0x00, 0x00, 0x01, 0x00, 0x88, 0x13 };
|
|
||||||
|
|
||||||
/* request atr */
|
|
||||||
rc = usb_control_xmit(0x40, 0x01, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
|
|
||||||
/* receive atr */
|
|
||||||
rc = usb_control_xmit(0xc0, 0x81, 0x0000, 0x0000, 0x0023, buffer);
|
|
||||||
if ((rc == -1) || (rc == 0)) {
|
|
||||||
/* failed, we should get an atr */
|
|
||||||
syslog(LOG_ERR, "etoken fatal: no ATR received");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = buffer[0];
|
|
||||||
if (rc < len) {
|
|
||||||
/* failed, we need to get a whole atr */
|
|
||||||
syslog(LOG_ERR, "etoken fatal: wrong ATR");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy atr */
|
|
||||||
usbtoken.atr = malloc(len);
|
|
||||||
memcpy(usbtoken.atr, buffer + 1, len);
|
|
||||||
usbtoken.atrlen = len;
|
|
||||||
|
|
||||||
/* ask for something strange */
|
|
||||||
rc = usb_control_xmit(0x40, 0x03, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
|
|
||||||
/* receive strange data */
|
|
||||||
rc = usb_control_xmit(0xc0, 0x83, 0x0000, 0x0000, 0x000d, buffer);
|
|
||||||
|
|
||||||
/* send something strange */
|
|
||||||
memcpy(buffer, cookie, sizeof(cookie));
|
|
||||||
rc = usb_control_xmit(0x40, 0x02, 0x0000, 0x0000, sizeof(cookie),
|
|
||||||
buffer);
|
|
||||||
if (rc != sizeof(cookie)) {
|
|
||||||
/* the whole cookie should have been send */
|
|
||||||
syslog(LOG_ERR, "etoken fatal: cookie not completly send: rc=%d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get strange answer */
|
|
||||||
rc = usb_control_xmit(0xc0, 0x82, 0x0000, 0x0000, 0x0001, buffer);
|
|
||||||
if (rc != 1) {
|
|
||||||
/* we should have got one byte */
|
|
||||||
syslog(LOG_ERR, "etoken fatal: did not receive one byte response to cookie: rc=%d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer[0] != 0) {
|
|
||||||
/* the answer should have bin 0x00 */
|
|
||||||
syslog(LOG_ERR, "etoken fatal: received one byte response to cookie but it is: %d!=0", buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int etoken_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
uint8_t wtx_resp[] = { 0xe0, 0xc3, 0x01, 0x01, 0xc3 };
|
|
||||||
uint8_t wtx_send[] = { 0x00, 0x00, 0x01, 0x00, 0x10, 0x27 };
|
|
||||||
uint8_t wtx_recv[] = { 0x00 };
|
|
||||||
|
|
||||||
/* waiting time extension works without this,
|
|
||||||
* but the windows driver send a magic sequence first
|
|
||||||
* and asks for a magic answer, so we copied this */
|
|
||||||
if (len_send == sizeof(wtx_resp)
|
|
||||||
&& memcmp(buf_send, wtx_resp, sizeof(wtx_resp) == 0)) {
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x40, 0x02, 0x0000, 0x0000,
|
|
||||||
sizeof(wtx_send), wtx_send);
|
|
||||||
|
|
||||||
if (rc != sizeof(wtx_send)) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"etoken fatal: wtx special send'd wrong len %d",
|
|
||||||
rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
rc = usb_control_xmit(0xc0, 0x82, 0x0000, 0x0000, 01,
|
|
||||||
buf_recv);
|
|
||||||
if (rc != sizeof(wtx_recv)) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"etoken fatal: wtx special recv'd wrong len %d",
|
|
||||||
rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
if (memcmp(buf_recv, wtx_recv, sizeof(wtx_recv) != 0)) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"etoken fatal: wtx special recv does not match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send via usb */
|
|
||||||
rc = usb_control_xmit(0x40, 0x06, 0x0000, 0x0000, len_send,
|
|
||||||
buf_send);
|
|
||||||
if (rc != len_send) {
|
|
||||||
syslog(LOG_ERR, "etoken fatal: received %d != %d",
|
|
||||||
rc, len_send);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* receive answer via usb */
|
|
||||||
rc = usb_control_xmit(0xc0, 0x86, 0x0000, 0x0000,
|
|
||||||
usbtoken.ifsc + 5, buf_recv);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "etoken fatal: receive answer rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*len_recv = rc;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,148 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
int eutron_init();
|
|
||||||
int eutron_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv);
|
|
||||||
|
|
||||||
const struct token_drv eutron_drv = {
|
|
||||||
.init = eutron_init,
|
|
||||||
.transmit = eutron_transmit,
|
|
||||||
.max_ifsc = 0x100,
|
|
||||||
.timeout = 2710,
|
|
||||||
.name = "Eutron CryptoIdentity",
|
|
||||||
};
|
|
||||||
|
|
||||||
char *eutron_products[] = { "73d/5/120", 0 };
|
|
||||||
|
|
||||||
int eutron_test(char *product)
|
|
||||||
{
|
|
||||||
char **p;
|
|
||||||
if (!product)
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
|
|
||||||
for (p = eutron_products; *p; p++) {
|
|
||||||
if (strcmp(product, *p) == 0) {
|
|
||||||
usbtoken.drv = eutron_drv;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int eutron_init()
|
|
||||||
{
|
|
||||||
int rc, lr, c;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
uint8_t cookie[] = { 0xff, 0x11, 0x98, 0x76 };
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0xa3, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
rc = usb_control_xmit(0x41, 0xa1, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
rc = usb_control_xmit(0x41, 0xa2, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
rc = usb_control_xmit(0x41, 0xa0, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
rc = usb_control_xmit(0x41, 0x09, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
|
|
||||||
lr = 0;
|
|
||||||
while (1) {
|
|
||||||
rc = usb_control_xmit(0xc1, 0x02, 0x0000, 0x0000, 0x0100,
|
|
||||||
&buffer[lr]);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"eutron fatal: receive answer rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
lr += rc;
|
|
||||||
rc = is_atr_complete(buffer, lr);
|
|
||||||
if (rc == USBTOKEN_OK)
|
|
||||||
break;
|
|
||||||
if (rc != USBTOKEN_INCOMPLETE)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
/* copy atr */
|
|
||||||
usbtoken.atr = malloc(lr);
|
|
||||||
memcpy(usbtoken.atr, buffer, lr);
|
|
||||||
usbtoken.atrlen = lr;
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x01, 0x0000, 0x0000,
|
|
||||||
sizeof(cookie), cookie);
|
|
||||||
|
|
||||||
c = 0;
|
|
||||||
lr = 0;
|
|
||||||
while (1) {
|
|
||||||
rc = usb_control_xmit(0xc1, 0x02, 0x0000, 0x0000, 0x0100,
|
|
||||||
&buffer[lr]);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"eutron fatal: receive answer rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
lr += rc;
|
|
||||||
if (lr >= 4)
|
|
||||||
break;
|
|
||||||
c++;
|
|
||||||
if (c > 20) {
|
|
||||||
syslog(LOG_ERR, "eutron fatal: looping forever");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x65, 0x98, 0x0000, 0x0000, buffer);
|
|
||||||
rc = usb_control_xmit(0x41, 0xa0, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int eutron_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv)
|
|
||||||
{
|
|
||||||
int rc, lr, c;
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x42, 0x01, 0x0000, 0x0000, len_send,
|
|
||||||
buf_send);
|
|
||||||
if (rc != len_send) {
|
|
||||||
syslog(LOG_ERR, "eutron fatal: received %d != %d", rc,
|
|
||||||
len_send);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
lr = 0;
|
|
||||||
c = 0;
|
|
||||||
while (1) {
|
|
||||||
rc = usb_control_xmit(0xc1, 0x02, 0x0000, 0x0000, 0x0100,
|
|
||||||
&buf_recv[lr]);
|
|
||||||
syslog(LOG_DEBUG, "rc %d, lr %d, len %d",
|
|
||||||
rc, lr, buf_recv[2]);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"eutron fatal: receive answer rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
lr += rc;
|
|
||||||
if (lr >= 4 && lr >= buf_recv[2] + 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
c++;
|
|
||||||
if (c > 10000) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"eutron fatal: timeout after 100s");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
} else {
|
|
||||||
struct timespec x;
|
|
||||||
x.tv_sec = 0;
|
|
||||||
x.tv_nsec = 50000000;
|
|
||||||
nanosleep(&x, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
*len_recv = lr;
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,182 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
int ikey2k_init();
|
|
||||||
int ikey2k_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv);
|
|
||||||
|
|
||||||
const struct token_drv ikey2k_drv = {
|
|
||||||
.init = ikey2k_init,
|
|
||||||
.transmit = ikey2k_transmit,
|
|
||||||
.max_ifsc = 0xb4, /* as used under windows */
|
|
||||||
.timeout = 10000,
|
|
||||||
.name = "Rainbow iKey 2000/2032",
|
|
||||||
};
|
|
||||||
|
|
||||||
char *ikey2k_products[] = { "4b9/1202/100", 0 };
|
|
||||||
|
|
||||||
int ikey2k_test(char *product)
|
|
||||||
{
|
|
||||||
char **p;
|
|
||||||
if (!product)
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
|
|
||||||
for (p = ikey2k_products; *p; p++) {
|
|
||||||
if (strcmp(product, *p) == 0) {
|
|
||||||
usbtoken.drv = ikey2k_drv;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ikey2k_init()
|
|
||||||
{
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
|
|
||||||
uint8_t expect5[] = { 0x0d, 0x63, 0x00, 0x05, 0x2d, 0x2d, 0xc0,
|
|
||||||
0x80, 0x80, 0x60, 0x80, 0x01, 0x19
|
|
||||||
};
|
|
||||||
#ifdef MANUAL_IFSC
|
|
||||||
uint8_t expect17[] =
|
|
||||||
{ 0x00, 0xe1, 0x01, 0xb4, 0x54, 0x40, 0x98, 0xc1 };
|
|
||||||
#endif /* MANUAL_IFSC */
|
|
||||||
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x00, 0x0000, 0x0000, 0x0040, buffer);
|
|
||||||
if (memcmp(buffer, expect5, sizeof(expect5)) != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: ikey2k urb 5 bad match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 6 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0002, buffer);
|
|
||||||
if (rc != 1 || buffer[0] != 0) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey2k fatal: urb 7 returned %d, first byte %hhx",
|
|
||||||
rc, buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x1901, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 8 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0019, buffer);
|
|
||||||
if (rc != 25) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 9 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 10 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0002, buffer);
|
|
||||||
if (rc != 1 || buffer[0] != 0) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey2k fatal: urb 11 returned %d, first byte %hhx",
|
|
||||||
rc, buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 12 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0020, buffer);
|
|
||||||
if (rc != 1 || buffer[0] != 0) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey2k fatal: urb 13 returned %d, first byte %hhx",
|
|
||||||
rc, buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x1901, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 14 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0019, buffer);
|
|
||||||
if (rc != 25) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 15 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbtoken.atr = malloc(rc);
|
|
||||||
if (!usbtoken.atr) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"fatal error: ikey2k could not malloc for atr");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
memcpy(usbtoken.atr, buffer, rc);
|
|
||||||
usbtoken.atrlen = rc;
|
|
||||||
|
|
||||||
#ifdef MANUAL_IFSC
|
|
||||||
buffer[0] = 0x74;
|
|
||||||
rc = usb_control_xmit(0x41, 0x17, 0xc100, 0xb401, 0x0001, buffer);
|
|
||||||
if (rc != 1) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 16 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0008, buffer);
|
|
||||||
if (memcmp(buffer, expect17, sizeof(expect17)) != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey2k fatal: urb 17 bad match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
#endif /* MANUAL_IFSC */
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ikey2k_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int value, index;
|
|
||||||
|
|
||||||
value = buf_send[1] << 8 | buf_send[0];
|
|
||||||
index = buf_send[3] << 8 | buf_send[2];
|
|
||||||
|
|
||||||
/* send via usb */
|
|
||||||
rc = usb_control_xmit(0x41, 0x17, value, index, len_send - 4,
|
|
||||||
&buf_send[4]);
|
|
||||||
if (rc != len_send - 4) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey2k fatal: transfer sending failed rc %d len %d",
|
|
||||||
rc, len_send);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* receive answer via usb */
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, usbtoken.ifsc,
|
|
||||||
buf_recv);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey2k fatal: transfer receive failed rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*len_recv = rc;
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
int ikey3k_init();
|
|
||||||
int ikey3k_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv);
|
|
||||||
|
|
||||||
const struct token_drv ikey3k_drv = {
|
|
||||||
.init = ikey3k_init,
|
|
||||||
.transmit = ikey3k_transmit,
|
|
||||||
.max_ifsc = 0xb4, /* as used under windows */
|
|
||||||
.timeout = 10000,
|
|
||||||
.name = "Rainbow iKey 3000",
|
|
||||||
};
|
|
||||||
|
|
||||||
char *ikey3k_products[] = { "4b9/1300/100", 0 };
|
|
||||||
|
|
||||||
int ikey3k_test(char *product)
|
|
||||||
{
|
|
||||||
char **p;
|
|
||||||
if (!product)
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
|
|
||||||
for (p = ikey3k_products; *p; p++) {
|
|
||||||
if (strcmp(product, *p) == 0) {
|
|
||||||
usbtoken.drv = ikey3k_drv;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ikey3k_init()
|
|
||||||
{
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
|
|
||||||
uint8_t expect5[] =
|
|
||||||
{ 0x0a, 0x61, 0x00, 0x07, 0x2d, 0x2d, 0xc0, 0x80, 0x80, 0x60 };
|
|
||||||
uint8_t expect11[] = { 0xff, 0x11, 0x11, 0xff };
|
|
||||||
#ifdef MANUAL_IFSC
|
|
||||||
uint8_t expect13[] =
|
|
||||||
{ 0x00, 0xe1, 0x01, 0xb4, 0x54, 0x40, 0x98, 0xc1 };
|
|
||||||
#endif /* MANUAL_IFSC */
|
|
||||||
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x00, 0x0000, 0x0000, 0x0040, buffer);
|
|
||||||
if (memcmp(buffer, expect5, sizeof(expect5)) != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 5 bad match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x0000, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 6 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0002, buffer);
|
|
||||||
if (rc != 1 || buffer[0] != 0) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey3k fataiL: urb 7 returned %d, first byte %hhx",
|
|
||||||
rc, buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x2005, 0x0000, 0x0000, buffer);
|
|
||||||
if (rc != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 8 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0020, buffer);
|
|
||||||
if (rc != 32) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 9 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc < 1 || (rc < buffer[0])) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: atr incomplete (%d/%hhd)",
|
|
||||||
rc, buffer[0]);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbtoken.atr = malloc(buffer[0]);
|
|
||||||
if (!usbtoken.atr) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: could not malloc for atr");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
memcpy(usbtoken.atr, &buffer[1], buffer[0]);
|
|
||||||
usbtoken.atrlen = buffer[0];
|
|
||||||
|
|
||||||
buffer[0] = 0x74;
|
|
||||||
rc = usb_control_xmit(0x41, 0x16, 0x0002, 0x0000, 0x0001, buffer);
|
|
||||||
if (rc != 1) {
|
|
||||||
syslog(LOG_ERR, "ikey3k urb 10 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0004, buffer);
|
|
||||||
if (memcmp(buffer, expect11, sizeof(expect11)) != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 11 bad match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
#ifdef MANUAL_IFSC
|
|
||||||
buffer[0] = 0x74;
|
|
||||||
rc = usb_control_xmit(0x41, 0x17, 0xc100, 0xb401, 0x0001, buffer);
|
|
||||||
if (rc != 1) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 12 returned %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, 0x0008, buffer);
|
|
||||||
if (memcmp(buffer, expect13, sizeof(expect13)) != 0) {
|
|
||||||
syslog(LOG_ERR, "ikey3k fatal: urb 13 bad match");
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
#endif /* MANUAL_IFSC */
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ikey3k_transmit(uint8_t * buf_send, int len_send,
|
|
||||||
uint8_t * buf_recv, int *len_recv)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
int value, index;
|
|
||||||
|
|
||||||
value = buf_send[1] << 8 | buf_send[0];
|
|
||||||
index = buf_send[3] << 8 | buf_send[2];
|
|
||||||
|
|
||||||
/* send via usb */
|
|
||||||
rc = usb_control_xmit(0x41, 0x17, value, index, len_send - 4,
|
|
||||||
&buf_send[4]);
|
|
||||||
if (rc != len_send - 4) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey3k fatal: tranfer sending failed rc %d len %d",
|
|
||||||
rc, len_send);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* receive answer via usb */
|
|
||||||
rc = usb_control_xmit(0xc1, 0x01, 0x0000, 0x0000, usbtoken.ifsc,
|
|
||||||
buf_recv);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"ikey3k fatal: tranfer receive failed rc %d", rc);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*len_recv = rc;
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
struct token usbtoken;
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
char *action, *device, *product;
|
|
||||||
int rc;
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
/* action should be "add".
|
|
||||||
* we will notice removes ourself. */
|
|
||||||
action = getenv("ACTION");
|
|
||||||
if (!action || strcmp(action, "add") != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((argc > 1) && (strcmp(argv[1], "nofork") == 0)) {
|
|
||||||
fprintf(stderr,"not forking to easy debugging");
|
|
||||||
} else {
|
|
||||||
pid = fork();
|
|
||||||
if (pid == -1) {
|
|
||||||
fprintf(stderr, "fork failed: %s (%d)", strerror(errno), errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (pid) {
|
|
||||||
/* parent process */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* child: continue */
|
|
||||||
}
|
|
||||||
|
|
||||||
openlog(SYSLOG_NAME, LOG_CONS | LOG_PERROR | LOG_PID, LOG_KERN);
|
|
||||||
|
|
||||||
product = getenv("PRODUCT");
|
|
||||||
{
|
|
||||||
if (eutron_test(product) == USBTOKEN_OK ||
|
|
||||||
etoken_test(product) == USBTOKEN_OK ||
|
|
||||||
ikey2k_test(product) == USBTOKEN_OK ||
|
|
||||||
ikey3k_test(product) == USBTOKEN_OK) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"found product : %s", usbtoken.drv.name);
|
|
||||||
} else {
|
|
||||||
syslog(LOG_ERR, "unknown product %s", product);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DEVICE should hold the path to the device file we need. */
|
|
||||||
device = getenv("DEVICE");
|
|
||||||
if (!device) {
|
|
||||||
syslog(LOG_ERR, "device not found, aborting!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the device might not be there right now. wait one second */
|
|
||||||
sleep(1);
|
|
||||||
usbtoken.usbfd = open(device, O_EXCL | O_RDWR);
|
|
||||||
if (usbtoken.usbfd == -1) {
|
|
||||||
syslog(LOG_ERR, "open device %s failed: %s, aborting!\n",
|
|
||||||
device, strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.drv.init() != USBTOKEN_OK) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_atr() != USBTOKEN_OK) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (increase_ifsc() != USBTOKEN_OK) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid_init() != USBTOKEN_OK) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"all slots in use. increased MAXTOKEN, recompile");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socket_init() != USBTOKEN_OK) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
struct pollfd pollfd[3];
|
|
||||||
pollfd[0].fd = usbtoken.usbfd;
|
|
||||||
pollfd[0].events = POLLIN | POLLPRI | POLLOUT;
|
|
||||||
pollfd[1].fd = usbtoken.unixfd;
|
|
||||||
pollfd[1].events = POLLIN | POLLPRI;
|
|
||||||
if (usbtoken.connfd) {
|
|
||||||
pollfd[2].fd = usbtoken.connfd;
|
|
||||||
pollfd[2].events = POLLIN | POLLPRI;
|
|
||||||
rc = poll(pollfd, 3, 1000);
|
|
||||||
} else {
|
|
||||||
rc = poll(pollfd, 2, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"poll returned error, aborting: %s!\n",
|
|
||||||
strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pollfd[0].revents) {
|
|
||||||
if ((pollfd[0].revents & 0x18) == 0x18) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"device removed. exiting.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* handle usb stuff */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.connfd && (pollfd[2].revents & POLLHUP)) {
|
|
||||||
socket_hangup();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pollfd[1].revents) {
|
|
||||||
/* handle unix socket (listen()ing) */
|
|
||||||
socket_accept();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usbtoken.connfd && pollfd[2].revents) {
|
|
||||||
if (socket_xmit() != USBTOKEN_OK)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ignore other poll results */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
char *pidfile;
|
|
||||||
|
|
||||||
void pid_exit()
|
|
||||||
{
|
|
||||||
if (pidfile) {
|
|
||||||
unlink(pidfile);
|
|
||||||
free(pidfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int pid_init()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXTOKEN - 1; i++) {
|
|
||||||
char buffer[1024];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
snprintf(buffer, sizeof(buffer), PIDFILE, i);
|
|
||||||
fd = open(buffer, O_CREAT|O_EXCL|O_WRONLY, 0644);
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pidfile = strdup(buffer);
|
|
||||||
snprintf(buffer, sizeof(buffer), "%d\n", getpid());
|
|
||||||
write(fd, buffer, strlen(buffer));
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
usbtoken.slot = i;
|
|
||||||
atexit(pid_exit);
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
|
@ -1,184 +0,0 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
#define MSG_ERROR -1
|
|
||||||
#define MSG_OK 0
|
|
||||||
#define MSG_TRANSMIT 3
|
|
||||||
#define MSG_LOCK 4
|
|
||||||
#define MSG_UNLOCK 5
|
|
||||||
|
|
||||||
char *socketpath;
|
|
||||||
|
|
||||||
void socket_exit()
|
|
||||||
{
|
|
||||||
if (socketpath) {
|
|
||||||
unlink(socketpath);
|
|
||||||
free(socketpath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket_init()
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct sockaddr_un ua;
|
|
||||||
int ualen;
|
|
||||||
mode_t oldmask;
|
|
||||||
|
|
||||||
usbtoken.unixfd = socket(PF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (usbtoken.unixfd == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"socket_init: socket failed: %s, aborting!\n",
|
|
||||||
strerror(errno));
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero(&ua, sizeof(ua));
|
|
||||||
ua.sun_family = AF_UNIX;
|
|
||||||
snprintf(ua.sun_path, sizeof(ua.sun_path), SOCKET, usbtoken.slot);
|
|
||||||
|
|
||||||
socketpath = strdup(ua.sun_path);
|
|
||||||
unlink(socketpath);
|
|
||||||
atexit(socket_exit);
|
|
||||||
|
|
||||||
ualen = sizeof(ua.sun_family) + strlen(ua.sun_path);
|
|
||||||
oldmask = umask(0);
|
|
||||||
rc = bind(usbtoken.unixfd, (struct sockaddr *) &ua, ualen);
|
|
||||||
umask(oldmask);
|
|
||||||
|
|
||||||
/* some error */
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"socket_init: bind on %s failed: %s(%d), aborting!\n",
|
|
||||||
ua.sun_path, strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = listen(usbtoken.unixfd, 1);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"socket_init: listen failed: %s(%d), aborting!\n",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = fcntl(usbtoken.unixfd, F_SETFL, O_NONBLOCK);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"socket_init: fcntl failed: %s(%d), aborting!\n",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket_accept()
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = accept(usbtoken.unixfd, NULL, 0);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "socket_accept: accept failed: %s(%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
if (usbtoken.connfd) {
|
|
||||||
close(rc);
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
usbtoken.connfd = rc;
|
|
||||||
|
|
||||||
rc = write(usbtoken.connfd, usbtoken.atr, usbtoken.atrlen);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"socket_accept: write failed: %s(%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket_hangup()
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = close(usbtoken.connfd);
|
|
||||||
usbtoken.connfd = 0;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int unix_write(uint8_t msg, int size)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = write(usbtoken.connfd, &msg, size);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "unix_write: write failed: %s(%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket_xmit()
|
|
||||||
{
|
|
||||||
uint8_t buf_read[1024];
|
|
||||||
int rc, len_read;
|
|
||||||
|
|
||||||
rc = read(usbtoken.connfd, buf_read, sizeof(buf_read));
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "socket_xmit: read failed: %s(%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
len_read = rc;
|
|
||||||
|
|
||||||
if (buf_read[0] == MSG_TRANSMIT) {
|
|
||||||
uint8_t buf_write[1024];
|
|
||||||
int len_write;
|
|
||||||
len_write = sizeof(buf_write) - 1;
|
|
||||||
|
|
||||||
rc = t1_process(&buf_read[1], len_read - 1,
|
|
||||||
&buf_write[1], &len_write);
|
|
||||||
if (rc != USBTOKEN_OK)
|
|
||||||
return rc;
|
|
||||||
buf_write[0] = MSG_TRANSMIT;
|
|
||||||
|
|
||||||
rc = write(usbtoken.connfd, buf_write, len_write + 1);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR,
|
|
||||||
"socket_xmit: write failed: %s(%d)",
|
|
||||||
strerror(errno), errno);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* all other commands are single byte commands */
|
|
||||||
if (len_read != 1) {
|
|
||||||
syslog(LOG_ERR, "socket_xmit: recv returned: %d",
|
|
||||||
len_read);
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_read[0] == MSG_LOCK) {
|
|
||||||
return unix_write(MSG_OK, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_read[0] == MSG_UNLOCK) {
|
|
||||||
return unix_write(MSG_OK, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return unix_write(MSG_ERROR, 1);
|
|
||||||
}
|
|
|
@ -1,545 +0,0 @@
|
||||||
/* imported from SCEZ chipcard library - T=1 routines
|
|
||||||
* This is probably the first full free/open source T=1 implementation.
|
|
||||||
* Copyright Matthias Bruestle 1999-2002
|
|
||||||
* For licensing, see the file LICENCE
|
|
||||||
*
|
|
||||||
* Copyright 2003 Andreas Jellinghaus <aj@dungeon.inka.de>
|
|
||||||
* Copyright 2003 Kevin Stefanik <kstef@mtppi.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
#define T1_CHECKSUM_LRC 0x00
|
|
||||||
#define T1_CHECKSUM_CRC 0x01
|
|
||||||
|
|
||||||
#define T1_MAX_BLKLEN 3+256+2+2
|
|
||||||
|
|
||||||
/* direction */
|
|
||||||
#define T1_TO_CARD 0x00
|
|
||||||
#define T1_FROM_CARD 0x01
|
|
||||||
|
|
||||||
#define PCB(x) (x[1])
|
|
||||||
static inline int is_t1_iblock(uint8_t pcb) { return (pcb & 0x80) == 0x00; }
|
|
||||||
static inline int is_t1_rblock(uint8_t pcb) { return (pcb & 0xC0) == 0x80; }
|
|
||||||
static inline int is_t1_sblock(uint8_t pcb) { return (pcb & 0xC0) == 0xC0; }
|
|
||||||
|
|
||||||
static inline int is_t1_other_error(uint8_t pcb) {return (pcb & 0xef) == 0x82;}
|
|
||||||
|
|
||||||
/* we send resync requests and get a response */
|
|
||||||
static inline int is_t1_resync_req(uint8_t pcb) { return pcb == 0xc0; }
|
|
||||||
static inline int is_t1_resync_res(uint8_t pcb) { return pcb == 0xe0; }
|
|
||||||
|
|
||||||
/* the card can request these */
|
|
||||||
static inline int is_t1_ifs_req(uint8_t pcb) { return pcb == 0xc1; }
|
|
||||||
static inline int is_t1_abort_req(uint8_t pcb) { return pcb == 0xc2; }
|
|
||||||
static inline int is_t1_wtx_req(uint8_t pcb) { return pcb == 0xc3; }
|
|
||||||
|
|
||||||
#define T1_PCB_IBLOCK 0x00
|
|
||||||
#define T1_PCB_RBLOCK 0x80
|
|
||||||
#define T1_PCB_SBLOCK 0xC0
|
|
||||||
#define T1_PCB_MASK 0xC0
|
|
||||||
|
|
||||||
/* S-Block parameter */
|
|
||||||
#define T1_S_RESYNCH 0x00
|
|
||||||
#define T1_S_IFS 0x01
|
|
||||||
#define T1_S_ABORT 0x02
|
|
||||||
#define T1_S_WTX 0x03
|
|
||||||
|
|
||||||
#define T1_S_REQUEST 0x00
|
|
||||||
#define T1_S_RESPONSE 0x20
|
|
||||||
|
|
||||||
/* R-Block parameter */
|
|
||||||
#define T1_R_OK 0x00
|
|
||||||
#define T1_R_EDC_ERROR 0x01
|
|
||||||
#define T1_R_OTHER_ERROR 0x02
|
|
||||||
|
|
||||||
/* ISO STD 3309 */
|
|
||||||
/* From: medin@catbyte.b30.ingr.com (Dave Medin)
|
|
||||||
* Subject: CCITT checksums
|
|
||||||
* Newsgroups: sci.electronics
|
|
||||||
* Date: Mon, 7 Dec 1992 17:33:39 GMT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Correct Table? */
|
|
||||||
|
|
||||||
static unsigned short crctab[256] = {
|
|
||||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
|
||||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
|
||||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
|
||||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
|
||||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
|
||||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
|
||||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
|
||||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
|
||||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
|
||||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
|
||||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
|
||||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
|
||||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
|
||||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
|
||||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
|
||||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
|
||||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
|
||||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
|
||||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
|
||||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
|
||||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
|
||||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
|
||||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
|
||||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
|
||||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
|
||||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
|
||||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
|
||||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
|
||||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
|
||||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
|
||||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
|
||||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Returns LRC of data */
|
|
||||||
|
|
||||||
uint8_t calculate_lrc(const uint8_t * data, int datalen)
|
|
||||||
{
|
|
||||||
uint8_t lrc = 0x00;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < datalen; i++)
|
|
||||||
lrc ^= data[i];
|
|
||||||
|
|
||||||
return lrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculates CRC of data */
|
|
||||||
|
|
||||||
void calculate_crc(const uint8_t * data, int datalen, uint8_t * crc)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned short tmpcrc = 0xFFFF;
|
|
||||||
|
|
||||||
for (i = 0; i < datalen; i++)
|
|
||||||
tmpcrc =
|
|
||||||
((tmpcrc >> 8) & 0xFF) ^ crctab[(tmpcrc ^ *data++) &
|
|
||||||
0xFF];
|
|
||||||
|
|
||||||
crc[0] = (tmpcrc >> 8) & 0xFF;
|
|
||||||
crc[1] = tmpcrc & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Appends RC */
|
|
||||||
|
|
||||||
int append_rc(uint8_t * data, int *datalen)
|
|
||||||
{
|
|
||||||
if (usbtoken.rc == T1_CHECKSUM_LRC) {
|
|
||||||
data[*datalen] = calculate_lrc(data, *datalen);
|
|
||||||
*datalen += 1;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
} else if (usbtoken.rc == T1_CHECKSUM_CRC) {
|
|
||||||
calculate_crc(data, *datalen, data + *datalen);
|
|
||||||
*datalen += 2;
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checks RC. */
|
|
||||||
|
|
||||||
int check_rc(const uint8_t * data, int datalen)
|
|
||||||
{
|
|
||||||
uint8_t rc[2];
|
|
||||||
uint8_t cmp[2];
|
|
||||||
|
|
||||||
if (usbtoken.rc == T1_CHECKSUM_LRC) {
|
|
||||||
/* Check LEN. */
|
|
||||||
if ((data[2] + 3 + 1) > datalen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc[1] = data[data[2] + 3];
|
|
||||||
cmp[1] = calculate_lrc(data, data[2] + 3);
|
|
||||||
return (rc[1] == cmp[1]);
|
|
||||||
} else if (usbtoken.rc == T1_CHECKSUM_CRC) {
|
|
||||||
/* Check LEN. */
|
|
||||||
if ((data[2] + 3 + 2) > datalen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
calculate_crc(data, data[2] + 3, cmp);
|
|
||||||
return (memcmp(data + data[2] + 3, cmp, 2) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Builds S-Block */
|
|
||||||
|
|
||||||
int build_neg_block(int type, int dir, int param, uint8_t * block,
|
|
||||||
int *len)
|
|
||||||
{
|
|
||||||
block[0] = usbtoken.nad;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case T1_S_RESYNCH:
|
|
||||||
block[1] = T1_PCB_SBLOCK | dir | T1_S_RESYNCH;
|
|
||||||
block[2] = 0x00;
|
|
||||||
*len = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T1_S_IFS:
|
|
||||||
block[1] = T1_PCB_SBLOCK | dir | T1_S_IFS;
|
|
||||||
block[2] = 0x01;
|
|
||||||
block[3] = (uint8_t) param;
|
|
||||||
*len = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T1_S_ABORT:
|
|
||||||
block[1] = T1_PCB_SBLOCK | dir | T1_S_ABORT;
|
|
||||||
block[2] = 0x00;
|
|
||||||
*len = 3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T1_S_WTX:
|
|
||||||
block[1] = T1_PCB_SBLOCK | dir | T1_S_WTX;
|
|
||||||
block[2] = 0x01;
|
|
||||||
block[3] = (uint8_t) param;
|
|
||||||
*len = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return (USBTOKEN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return append_rc(block, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Builds R-Block */
|
|
||||||
|
|
||||||
int build_retry_block(int type, uint8_t * block, int *len)
|
|
||||||
{
|
|
||||||
block[0] = usbtoken.nad;
|
|
||||||
block[2] = 0x00;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case T1_R_OK:
|
|
||||||
if (usbtoken.nr)
|
|
||||||
block[1] = 0x90;
|
|
||||||
else
|
|
||||||
block[1] = 0x80;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T1_R_EDC_ERROR:
|
|
||||||
if (usbtoken.nr)
|
|
||||||
block[1] = 0x91;
|
|
||||||
else
|
|
||||||
block[1] = 0x81;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T1_R_OTHER_ERROR:
|
|
||||||
if (usbtoken.nr)
|
|
||||||
block[1] = 0x92;
|
|
||||||
else
|
|
||||||
block[1] = 0x82;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*len = 3;
|
|
||||||
return append_rc(block, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Builds I-Block */
|
|
||||||
|
|
||||||
int build_data_block(int more, const uint8_t * data, int datalen,
|
|
||||||
uint8_t * block, int *blocklen)
|
|
||||||
{
|
|
||||||
block[0] = usbtoken.nad;
|
|
||||||
|
|
||||||
block[1] = 0x00;
|
|
||||||
if (usbtoken.ns)
|
|
||||||
block[1] |= 0x40;
|
|
||||||
if (more)
|
|
||||||
block[1] |= 0x20;
|
|
||||||
|
|
||||||
if (datalen > usbtoken.ifsc)
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
block[2] = (uint8_t) datalen;
|
|
||||||
|
|
||||||
memcpy(block + 3, data, datalen);
|
|
||||||
|
|
||||||
*blocklen = datalen + 3;
|
|
||||||
return append_rc(block, blocklen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns N(R) or N(S) from R/I-Block. */
|
|
||||||
|
|
||||||
int get_sequence(const uint8_t * block)
|
|
||||||
{
|
|
||||||
if (is_t1_rblock(PCB(block))) {
|
|
||||||
return (block[1] & 0x10) ? 0x01 : 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_iblock(PCB(block))) {
|
|
||||||
return (block[1] & 0x40) ? 0x01 : 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int t1_process(uint8_t * apdu_cmd, int apdu_cmdlen,
|
|
||||||
uint8_t * apdu_rsp, int *apdu_rsplen)
|
|
||||||
{
|
|
||||||
int sendptr; /* Points to begining of unsent data. */
|
|
||||||
int sendlen;
|
|
||||||
|
|
||||||
uint8_t block[T1_MAX_BLKLEN];
|
|
||||||
uint8_t rblock[T1_MAX_BLKLEN];
|
|
||||||
int blocklen;
|
|
||||||
int rblocklen;
|
|
||||||
|
|
||||||
uint8_t rsp[256 + 3];
|
|
||||||
uint8_t rsplen;
|
|
||||||
|
|
||||||
int more; /* More data to send. */
|
|
||||||
int direction; /* It's ICCs turn to send I-Blocks. */
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
int errcntr = 0;
|
|
||||||
int rerrcntr = 0;
|
|
||||||
|
|
||||||
start:
|
|
||||||
*apdu_rsplen = 0;
|
|
||||||
direction = T1_TO_CARD;
|
|
||||||
rsplen = 0;
|
|
||||||
sendptr = 0;
|
|
||||||
sendlen = apdu_cmdlen;
|
|
||||||
|
|
||||||
if (sendlen > usbtoken.ifsc) {
|
|
||||||
sendlen = usbtoken.ifsc;
|
|
||||||
more = 1;
|
|
||||||
} else {
|
|
||||||
more = 0;
|
|
||||||
}
|
|
||||||
rc = build_data_block(more, apdu_cmd, sendlen, block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
sendptr += sendlen;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
rblocklen = sizeof(block);
|
|
||||||
rc = usbtoken.drv.transmit(block, blocklen, rblock,
|
|
||||||
&rblocklen);
|
|
||||||
|
|
||||||
/* communication error ? abort. */
|
|
||||||
if (rc != USBTOKEN_OK) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_other_error(PCB(rblock))) {
|
|
||||||
/* other error, request resync */
|
|
||||||
rc = build_neg_block(T1_S_RESYNCH, T1_S_REQUEST,
|
|
||||||
rblock[3], block,
|
|
||||||
&blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* length or rc error ? try three times. */
|
|
||||||
if (!check_rc(rblock, rblocklen)) {
|
|
||||||
errcntr++;
|
|
||||||
|
|
||||||
if (errcntr > 3) {
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = build_retry_block(T1_R_EDC_ERROR,
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ah, no length or rc error. reset counter. */
|
|
||||||
errcntr = 0;
|
|
||||||
|
|
||||||
/* shall we resend the last block ? try thee times. */
|
|
||||||
if (is_t1_rblock(PCB(rblock))) {
|
|
||||||
rerrcntr++;
|
|
||||||
|
|
||||||
if (rerrcntr > 3) {
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction == T1_FROM_CARD) {
|
|
||||||
/* Card is sending I-Blocks, so send R-Block. */
|
|
||||||
rc = build_retry_block(T1_R_OK,
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_sequence(rblock) == usbtoken.ns) {
|
|
||||||
/* N(R) is old N(S),
|
|
||||||
* so resend I-Block. */
|
|
||||||
sendptr -= sendlen;
|
|
||||||
} else {
|
|
||||||
/* N(R) is next N(S),
|
|
||||||
* so make next I-Block and send it. */
|
|
||||||
|
|
||||||
/* Check if data available. */
|
|
||||||
if (more == 0) {
|
|
||||||
/* last block was with pcb: bit6=0
|
|
||||||
* (no more following blocks)
|
|
||||||
* so there is no more data to send.
|
|
||||||
* if the card is waiting for
|
|
||||||
* additional data, then it is wrong.
|
|
||||||
* comm error! */
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change N(S) to new value. */
|
|
||||||
usbtoken.ns ^= 1;
|
|
||||||
/* Make next I-Block. */
|
|
||||||
|
|
||||||
/* Clear error counter */
|
|
||||||
rerrcntr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendlen = apdu_cmdlen - sendptr;
|
|
||||||
if (sendlen > usbtoken.ifsc) {
|
|
||||||
sendlen = usbtoken.ifsc;
|
|
||||||
} else {
|
|
||||||
more = 0;
|
|
||||||
}
|
|
||||||
rc = build_data_block(more, apdu_cmd +
|
|
||||||
sendptr, sendlen, block,
|
|
||||||
&blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
sendptr += sendlen;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we shall not resend the last block ? reset error counter. */
|
|
||||||
rerrcntr = 0;
|
|
||||||
|
|
||||||
/* I-Block */
|
|
||||||
if (is_t1_iblock(PCB(rblock))) {
|
|
||||||
|
|
||||||
if (direction == T1_TO_CARD) {
|
|
||||||
/* Change N(S) to new value. */
|
|
||||||
usbtoken.ns ^= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
direction = T1_FROM_CARD;
|
|
||||||
|
|
||||||
if (get_sequence(rblock) != usbtoken.nr) {
|
|
||||||
/* Card is sending wrong I-Block, so send R-Block. */
|
|
||||||
rc = build_retry_block(T1_R_OTHER_ERROR,
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy data. */
|
|
||||||
if (rblock[2] > (256 + 2 - rsplen)) {
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(rsp + rsplen, rblock + 3, rblock[2]);
|
|
||||||
rsplen += rblock[2];
|
|
||||||
|
|
||||||
if ((rblock[1] >> 5) & 1) {
|
|
||||||
/* More data available. */
|
|
||||||
|
|
||||||
/* Change N(R) to new value. */
|
|
||||||
usbtoken.nr ^= 1;
|
|
||||||
|
|
||||||
/* more fragments to come */
|
|
||||||
rc = build_retry_block(T1_R_OK,
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Last block. */
|
|
||||||
|
|
||||||
/* Change N(R) to new value. */
|
|
||||||
usbtoken.nr ^= 1;
|
|
||||||
|
|
||||||
if (rsplen < 2) {
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(apdu_rsp, rsp, rsplen);
|
|
||||||
*apdu_rsplen = rsplen;
|
|
||||||
|
|
||||||
rc = USBTOKEN_OK;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_resync_res(PCB(rblock))) {
|
|
||||||
/* resync: start from scratch */
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_wtx_req(PCB(rblock))) {
|
|
||||||
/* request waiting time extension */
|
|
||||||
rc = build_neg_block(T1_S_WTX,
|
|
||||||
T1_S_RESPONSE, rblock[3],
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_ifs_req(PCB(rblock))) {
|
|
||||||
/* the card want's to set a different ifsc. */
|
|
||||||
/* acknowledge */
|
|
||||||
rc = build_neg_block(T1_S_IFS,
|
|
||||||
T1_S_RESPONSE, rblock[3],
|
|
||||||
block, &blocklen);
|
|
||||||
if (rc) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
usbtoken.ifsc = rblock[3];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_t1_abort_req(PCB(rblock))) {
|
|
||||||
/* S-Block ABORT Request */
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
syslog(LOG_ERR, "t1 fatal: unknown pcb %d",PCB(rblock));
|
|
||||||
rc = USBTOKEN_ERROR;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
memset(block, 0, sizeof(block));
|
|
||||||
memset(rblock, 0, sizeof(rblock));
|
|
||||||
memset(rsp, 0, sizeof(rsp));
|
|
||||||
return rc;
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <linux/usbdevice_fs.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
#include "usbtoken.h"
|
|
||||||
|
|
||||||
#ifdef USB_DEBUG
|
|
||||||
void debug_hexdump(char *msg, uint8_t * buf, int size)
|
|
||||||
{
|
|
||||||
char line[1024];
|
|
||||||
const char hex[16] =
|
|
||||||
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
|
|
||||||
'c', 'd', 'e', 'f'
|
|
||||||
};
|
|
||||||
int n, i, max;
|
|
||||||
|
|
||||||
i = max = 0;
|
|
||||||
while (i < size) {
|
|
||||||
snprintf(line, sizeof(line), "%s %04x:", msg, i);
|
|
||||||
n = strlen(line);
|
|
||||||
|
|
||||||
max = i + 16;
|
|
||||||
if (max > size) {
|
|
||||||
max = size;
|
|
||||||
}
|
|
||||||
while (i < max) {
|
|
||||||
line[n++] = ' ';
|
|
||||||
line[n++] = hex[buf[i] / 16];
|
|
||||||
line[n++] = hex[buf[i] % 16];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
line[n++] = 0;
|
|
||||||
syslog(LOG_DEBUG, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* USB_DEBUG */
|
|
||||||
|
|
||||||
int usb_control_xmit(int type, int req, int value, int index, int size,
|
|
||||||
uint8_t * buf)
|
|
||||||
{
|
|
||||||
struct usbdevfs_ctrltransfer ctrl;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
ctrl.requesttype = type;
|
|
||||||
ctrl.request = req;
|
|
||||||
ctrl.value = value;
|
|
||||||
ctrl.index = index;
|
|
||||||
ctrl.length = size;
|
|
||||||
ctrl.data = buf;
|
|
||||||
ctrl.timeout = usbtoken.drv.timeout;
|
|
||||||
|
|
||||||
#ifdef USB_DEBUG
|
|
||||||
syslog(LOG_DEBUG,
|
|
||||||
"usb xmit %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx\n",
|
|
||||||
type, req, value & 0xff, value >> 8, index & 0xff,
|
|
||||||
index >> 8, size & 0xff, size >> 8);
|
|
||||||
|
|
||||||
if (!(type & 0x80))
|
|
||||||
debug_hexdump("Sending:", buf, size);
|
|
||||||
#endif /* USB_DEBUG */
|
|
||||||
|
|
||||||
rc = ioctl(usbtoken.usbfd, USBDEVFS_CONTROL, &ctrl);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "usb ioctl control transfer failed:%s\n",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
#ifdef USB_DEBUG
|
|
||||||
if (type & 0x80)
|
|
||||||
debug_hexdump("Received:", buf, rc);
|
|
||||||
#endif /* USB_DEBUG */
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usb_reset()
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = ioctl(usbtoken.usbfd, USBDEVFS_RESET, NULL);
|
|
||||||
if (rc == -1) {
|
|
||||||
syslog(LOG_ERR, "usb ioctl reset failed:%s\n",
|
|
||||||
strerror(errno));
|
|
||||||
return USBTOKEN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBTOKEN_OK;
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
#ifndef _USBTOKEN_H
|
|
||||||
#define _USBTOKEN_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define SYSLOG_NAME "usbtoken"
|
|
||||||
#define PIDFILE "/var/run/usbtoken%d.pid"
|
|
||||||
#define SOCKET "/var/run/usbtoken/socket%d"
|
|
||||||
#define UMASK 0000 /* used while creating the socket */
|
|
||||||
#define MAXTOKEN 10
|
|
||||||
#define USBTOKEN_OK 0
|
|
||||||
#define USBTOKEN_ERROR 1
|
|
||||||
#define USBTOKEN_INCOMPLETE 2
|
|
||||||
|
|
||||||
struct token_drv {
|
|
||||||
int (*init) ();
|
|
||||||
int (*transmit) (uint8_t * send, int send_len, uint8_t * recv,
|
|
||||||
int *recv_len);
|
|
||||||
int max_ifsc;
|
|
||||||
int timeout;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct token {
|
|
||||||
struct token_drv drv;
|
|
||||||
int unixfd;
|
|
||||||
int connfd;
|
|
||||||
int usbfd;
|
|
||||||
int usbvendor;
|
|
||||||
int usbproduct;
|
|
||||||
int slot;
|
|
||||||
int ifsc;
|
|
||||||
int rc; /* redundancy check */
|
|
||||||
int nad; /* nad byte */
|
|
||||||
int nr; /* next r block (0|1) */
|
|
||||||
int ns; /* next s block (0|1) */
|
|
||||||
uint8_t *atr;
|
|
||||||
int atrlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct token usbtoken;
|
|
||||||
|
|
||||||
int etoken_test(char *product);
|
|
||||||
int eutron_test(char *product);
|
|
||||||
int ikey2k_test(char *product);
|
|
||||||
int ikey3k_test(char *product);
|
|
||||||
|
|
||||||
/* atr.c */
|
|
||||||
int parse_atr();
|
|
||||||
int increase_ifsc();
|
|
||||||
int is_atr_complete(uint8_t * buffer, int lr);
|
|
||||||
|
|
||||||
/* pid.c */
|
|
||||||
void pid_exit();
|
|
||||||
int pid_init();
|
|
||||||
|
|
||||||
/* socket.c */
|
|
||||||
int socket_init();
|
|
||||||
int socket_accept();
|
|
||||||
int socket_hangup();
|
|
||||||
int socket_xmit();
|
|
||||||
|
|
||||||
/* t1.c */
|
|
||||||
int t1_process(uint8_t * apdu_cmd, int apdu_cmdlen,
|
|
||||||
uint8_t * apdu_rsp, int *apdu_rsplen);
|
|
||||||
|
|
||||||
/* usb.c */
|
|
||||||
void debug_hexdump(char *msg, uint8_t * buf, int size);
|
|
||||||
int usb_control_xmit(int type, int req, int value, int index,
|
|
||||||
int size, uint8_t * buf);
|
|
||||||
int usb_reset();
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue