summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Rees <rees@cvs.openbsd.org>2001-05-22 15:35:59 +0000
committerJim Rees <rees@cvs.openbsd.org>2001-05-22 15:35:59 +0000
commit8a0717bef7427805d78da4ed891a26cc68fef3ce (patch)
tree2c666c477bbec6e3145ebde6ab240e54f2573a85
parentd649f2222963a4768b7f060b2797f8df0cb4a152 (diff)
Initial commit of libsectok (secure token)
used for ISO 7816 smart cards and iButtons, but also extensible to other types of secure tokens. Also include a "driver" (dynamic library) for the Todos reader.
-rw-r--r--lib/libsectok/Makefile7
-rw-r--r--lib/libsectok/ifd/Makefile7
-rw-r--r--lib/libsectok/ifd/todos_ag/Makefile8
-rw-r--r--lib/libsectok/ifd/todos_ag/atr.c340
-rw-r--r--lib/libsectok/ifd/todos_ag/ifdhandler.c275
-rw-r--r--lib/libsectok/ifd/todos_ag/scT1.c172
-rw-r--r--lib/libsectok/ifd/todos_ag/scio.c455
-rw-r--r--lib/libsectok/ifd/todos_ag/scrw.c274
-rw-r--r--lib/libsectok/ifd/todos_ag/shlib_version2
-rw-r--r--lib/libsectok/ifd/todos_ag/todos_scrw.h170
-rw-r--r--lib/libsectok/lib/Makefile16
-rw-r--r--lib/libsectok/lib/atr.c348
-rw-r--r--lib/libsectok/lib/cmdtab.c140
-rw-r--r--lib/libsectok/lib/input.c101
-rw-r--r--lib/libsectok/lib/r1r2.c155
-rw-r--r--lib/libsectok/lib/readers.c53
-rw-r--r--lib/libsectok/lib/sc7816.c490
-rw-r--r--lib/libsectok/lib/sectok.h191
-rw-r--r--lib/libsectok/lib/shlib_version2
19 files changed, 3206 insertions, 0 deletions
diff --git a/lib/libsectok/Makefile b/lib/libsectok/Makefile
new file mode 100644
index 00000000000..41636cd49d6
--- /dev/null
+++ b/lib/libsectok/Makefile
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.1 2001/05/22 15:35:56 rees Exp $
+
+.include <bsd.own.mk>
+
+SUBDIR= lib ifd
+
+.include <bsd.subdir.mk>
diff --git a/lib/libsectok/ifd/Makefile b/lib/libsectok/ifd/Makefile
new file mode 100644
index 00000000000..74ab7e7c9ac
--- /dev/null
+++ b/lib/libsectok/ifd/Makefile
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.1 2001/05/22 15:35:57 rees Exp $
+
+.include <bsd.own.mk>
+
+SUBDIR= todos_ag
+
+.include <bsd.subdir.mk>
diff --git a/lib/libsectok/ifd/todos_ag/Makefile b/lib/libsectok/ifd/todos_ag/Makefile
new file mode 100644
index 00000000000..c7528e1861a
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/Makefile
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2001/05/22 15:35:57 rees Exp $
+
+LIB= todos_ag
+LIBDIR= /usr/lib/ifd
+LIBMODE= 644
+SRCS= atr.c ifdhandler.c scT1.c scio.c scrw.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libsectok/ifd/todos_ag/atr.c b/lib/libsectok/ifd/todos_ag/atr.c
new file mode 100644
index 00000000000..b510e07e6a0
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/atr.c
@@ -0,0 +1,340 @@
+/*
+ * Parse smart card atr, return proto params
+ *
+ * Jim Rees, University of Michigan CITI
+ */
+static char *rcsid = "$Id: atr.c,v 1.1 2001/05/22 15:35:57 rees Exp $";
+
+#include <stdio.h>
+#include <string.h>
+
+#include "todos_scrw.h"
+
+/*
+ * 7816 says ATR will appear within 40000 clocks (12 msec)
+ * BUT some cards violate the spec and require more time
+ */
+#define ATRTIME 120
+#define BYTETIME 1000
+
+/* Global interface bytes */
+#define TA1 (tpb[0][0])
+#define TB1 (tpb[0][1])
+#define TC1 (tpb[0][2])
+#define TD1 (tpb[0][3])
+#define TC2 (tpb[1][2])
+#define TA2 (tpb[1][0])
+
+static char dummyatr[] = {0x3b, 0x25, 0x00, 0x44, 0x55, 0x4d, 0x4d, 0x59};
+
+/* Inversion table, for inverse convention */
+unsigned char scinvert[] = {
+ 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
+ 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
+ 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17,
+ 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
+ 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b,
+ 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
+ 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13,
+ 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
+ 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
+ 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
+ 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15,
+ 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
+ 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19,
+ 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
+ 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11,
+ 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
+ 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e,
+ 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
+ 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16,
+ 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
+ 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a,
+ 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
+ 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12,
+ 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
+ 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c,
+ 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
+ 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
+ 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
+ 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18,
+ 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
+ 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10,
+ 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00,
+};
+
+/* 7816-3 1997 Table 7, 8 */
+static short Ftab[] = { 372, 372, 558, 744, 1116, 1488, 1860, -1,
+ -1, 512, 768, 1024, 1536, 2048, -1, -1 };
+static short Dtab[] = { -1, 1, 2, 4, 8, 16, 32, -1, 12, 20, -1, -1, -1, -1, -1, -1 };
+
+/*
+ * Table generated by mkFDtab.
+ */
+
+static struct bps {
+ unsigned char Fi, Di;
+ long bps;
+} bps[] = {
+ { 0x01, 0x08, 115464 },
+ { 0x09, 0x05, 111856 },
+ { 0x0b, 0x06, 111840 },
+ { 0x03, 0x08, 57732 },
+ { 0x09, 0x04, 55928 },
+ { 0x0a, 0x08, 55920 },
+ { 0x0b, 0x05, 55920 },
+ { 0x0d, 0x06, 55904 },
+ { 0x03, 0x04, 38488 },
+ { 0x01, 0x03, 38488 },
+ { 0x04, 0x08, 38484 },
+ { 0x06, 0x09, 38480 },
+ { 0x05, 0x05, 38480 },
+ { 0x0a, 0x04, 37280 },
+ { 0x0c, 0x05, 37280 },
+ { 0x05, 0x08, 28860 },
+ { 0x09, 0x03, 27964 },
+ { 0x0c, 0x08, 27960 },
+ { 0x0b, 0x04, 27960 },
+ { 0x0d, 0x05, 27952 },
+ { 0x06, 0x08, 23088 },
+ { 0x01, 0x02, 19244 },
+ { 0x03, 0x03, 19244 },
+ { 0x05, 0x04, 19240 },
+ { 0x0a, 0x03, 18640 },
+ { 0x0c, 0x04, 18640 },
+ { 0x09, 0x02, 13982 },
+ { 0x0b, 0x03, 13980 },
+ { 0x0d, 0x04, 13976 },
+ { 0x02, 0x02, 12828 },
+ { 0x04, 0x03, 12828 },
+ { 0, 0, 0 }
+};
+
+
+#define SCGETC if (todos_scgetc(ttyn, ap, (len ? BYTETIME : ATRTIME)) != SCEOK) goto timedout; else len++
+
+int
+todos_get_atr(int ttyn, int flags, unsigned char *atr, struct scparam *param)
+{
+ int len, i, c, t, ts, t0, tck, nhb, pbn;
+ int F, D, Fi, Di, N, etu, WI;
+ unsigned char *ap, *hb;
+ unsigned char tpb[8][4];
+ int hiproto = 0;
+
+ if (flags & SCRFORCE) {
+ len = sizeof dummyatr;
+ memcpy(atr, dummyatr, len);
+ param->t = 0;
+ param->etu = 100;
+ param->n = 0;
+ param->cwt = 1000;
+ return len;
+ }
+
+#ifndef DEBUG
+ flags &= ~SCRV;
+#endif
+
+ ap = atr;
+ len = 0;
+
+ /* TS */
+ SCGETC;
+ ts = *ap++;
+ if (ts == 0x3) {
+ if (flags & SCRV)
+ printf("inverse conversion\n");
+ todos_scsetflags(ttyn, SCOINVRT, SCOINVRT);
+ ts = scinvert[ts];
+ }
+ if (ts != 0x3b && ts != 0x3f) {
+ if (flags & SCRV)
+ printf("TS=%02x (not default timing)\n", ts);
+ param->t = -1;
+ return 0;
+ }
+
+ /* T0 */
+ SCGETC;
+ t0 = *ap++;
+ nhb = t0 & 0xf;
+
+ /* Fill in defaults */
+ TA1 = 0x11;
+ TB1 = 0x4d;
+ TC1 = 0x00;
+ TC2 = 10;
+ TA2 = 0xff;
+ TD1 = 0;
+
+ Fi = 1;
+ Di = 1;
+
+ /* Get up to 8 sets of protocol bytes */
+ for (i = 0; i < 8; i++) {
+ tpb[i][3] = 0;
+ for (pbn = 0; pbn < 4; pbn++) {
+ /* If T0 (or TD(i)) indicates presence of proto byte, get it */
+ if (t0 & (1 << (4 + pbn))) {
+ SCGETC;
+ tpb[i][pbn] = *ap++;
+ }
+ }
+ t = tpb[i][3] & 0xf;
+ if (t > hiproto)
+ hiproto = t;
+
+ if (flags & SCRV) {
+ printf("proto %d T=%d", i + 1, t);
+ for (pbn = 0; pbn < 4; pbn++)
+ if (t0 & (1 << (4 + pbn)))
+ printf(" T%c%d=%02x", 'A' + pbn, i + 1, tpb[i][pbn]);
+ printf("\n");
+ }
+
+ t0 = tpb[i][3];
+ if (!(t0 & 0xf0))
+ break;
+ }
+
+ /* Historical bytes */
+ if (nhb) {
+ for (i = 0; i < nhb; i++) {
+ SCGETC;
+ ap++;
+ }
+ if ((flags & SCRV))
+ printf("%d historical bytes\n", nhb);
+ }
+
+ /* TCK */
+ if (hiproto > 0) {
+ SCGETC;
+ ap++;
+ tck = 0;
+ for (i = 1; i < len; i++)
+ tck ^= atr[i];
+ if (tck != 0 && (flags & SCRV))
+ printf("Checksum failed, TCK=%x sum=%x\n", atr[len-1], tck);
+ }
+
+ /*
+ * I'm a little unclear on this. If TA2 is present, it indicates a specific mode.
+ * Else it's negotiable, and starts out with proto 1?
+ * 7816-3 6.6.1
+ */
+ if (TA2 != 0xff)
+ t = TA2 & 0xf;
+ else
+ t = TD1 & 0xf;
+
+ /* Todos reader won't do higher speeds */
+ if (!(flags & SCRTODOS)) {
+ for (i = 0; bps[i].bps; i++) {
+ if (((TA1 >> 4) & 0xf) >= bps[i].Fi && (TA1 & 0xf) >= bps[i].Di) {
+ int j;
+ unsigned char c;
+ static unsigned char pps[4] = {0xff, 0x10, 0, 0};
+
+ pps[2] = (bps[i].Fi << 4) | bps[i].Di;
+ pps[3] = 0;
+
+ if (flags & SCRV)
+ printf("speed %ld\n", bps[i].bps);
+
+#ifdef SCPPS
+ /* Compute checksum */
+ for (j = 0; j < 3; j++)
+ pps[3] ^= pps[j];
+
+ for (j = 0; j < 4; j++)
+ todos_scputc(ttyn, pps[j]);
+ for (j = 0; j < 4; j++)
+ if (todos_scgetc(ttyn, &c, 100) != SCEOK || c != pps[j])
+ break;
+ if (j != 4)
+ continue;
+ if (todos_scsetspeed(ttyn, bps[i].bps) < 0) {
+ /* We already sent the pps, can't back out now, so fail. */
+ if (flags & SCRV)
+ printf("scsetspeed %ld failed\n", bps[i].bps);
+ param->t = -1;
+ return len;
+ }
+#endif
+ Fi = bps[i].Fi;
+ Di = bps[i].Di;
+ break;
+ }
+ }
+ }
+
+ F = Ftab[Fi];
+ D = Dtab[Di];
+ N = TC1;
+
+ /* 1/f = 1/3.579545 ~= 50/179; etu in microsec */
+ param->etu = etu = (F * 50L) / (D * 179L);
+ param->n = (N < 255) ? N : 0;
+
+ if (flags & SCRV) {
+ printf("%d etu = %d F / %d D * 3.58 f\n", etu, F, D);
+ if (N)
+ printf("%d N\n", N);
+ }
+
+ if (t == 0) {
+ WI = TC2;
+
+ /* cwt is in milliseconds */
+ param->cwt = (960L * WI * F) / 3580L;
+ if ((flags & SCRV) && WI != 10)
+ printf("%d cwt = (960 * %d WI * %d F) / 3.58 f / 1000\n",
+ param->cwt, WI, F);
+ } else if (t == 1) {
+ /* add 100 to each for engineering safety margin */
+ param->cwt = (11L + (1 << (TB1 & 0xf))) * etu / 1000 + 100;
+ param->bwt = (11L * etu / 1000L) + ((1 << ((TB1 >> 4) & 0xf)) * 100) + 100;
+ if (flags & SCRV)
+ printf("%d cwt, %d bwt\n", param->cwt, param->bwt);
+ }
+ param->t = t;
+ return len;
+
+ timedout:
+ if (flags & SCRV)
+ printf("timed out after %d atr bytes\n", len);
+ param->t = -1;
+ return 0;
+}
+
+/*
+copyright 1997, 1999, 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/ifd/todos_ag/ifdhandler.c b/lib/libsectok/ifd/todos_ag/ifdhandler.c
new file mode 100644
index 00000000000..2455979a9bb
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/ifdhandler.c
@@ -0,0 +1,275 @@
+/*
+ * IFD handler for CITI sc7816 dumb reader driver
+ *
+ * Jim Rees, University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: ifdhandler.c,v 1.1 2001/05/22 15:35:57 rees Exp $";
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <string.h>
+
+#include "todos_scrw.h"
+
+/* capability table */
+struct cap_entry {
+ u_long tag;
+ int flags;
+} cap_table[] = {
+ {TAG_OPEN_FLAGS, 0}, /* open flags */
+ {TAG_RESET_FLAGS, 0}, /* reset flags */
+ {0, 0} /* terminator */
+};
+
+/* pcsc cruft */
+#define MAX_ATR_SIZE 33
+#define IFD_POWER_UP 500
+#define IFD_POWER_DOWN 501
+#define IFD_RESET 502
+#define IFD_ERROR_NOT_SUPPORTED 606
+#define IFD_ERROR_POWER_ACTION 608
+#define IFD_COMMUNICATION_ERROR 612
+#define IFD_NOT_SUPPORTED 614
+#define IFD_ICC_PRESENT 615
+#define IFD_ICC_NOT_PRESENT 616
+#define TAG_IFD_ATR 0x303
+
+struct SCARD_IO_HEADER {
+ u_long Protocol, Length;
+};
+
+static int CT_ttyn;
+static int CT_atrlen;
+static unsigned char CT_atr[MAX_ATR_SIZE];
+
+static short silly_channels[] = {
+ 0x3F8, 0x2F8, 0x3E8, 0x2E8, -1
+};
+
+u_long
+IO_Create_Channel(u_long ChannelId)
+{
+ int i, ttyn;
+
+#ifdef DEBUG
+ fprintf (stderr, "IO_Create_Channel: ChannelId == %06x\n", ChannelId);
+#endif /* DEBUG */
+
+ if ((ChannelId & 0xffff0000) != 0x10000)
+ return IFD_NOT_SUPPORTED;
+
+ ttyn = ChannelId & 0xffff;
+ for (i = 0; silly_channels[i] > 0; i++) {
+ if (silly_channels[i] == ttyn) {
+ ttyn = i;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "IO_Create_Channel: ttyn == %d, flags == %d\n",
+ ttyn, cap_table[0].flags);
+#endif /* DEBUG */
+
+ CT_ttyn = todos_scopen(ttyn, cap_table[0].flags, NULL);
+
+#ifdef DEBUG
+ fprintf (stderr, "IO_Create_Channel: todos_scopen() returns %d\n", CT_ttyn);
+#endif /* DEBUG */
+
+ return (CT_ttyn < 0) ? IFD_COMMUNICATION_ERROR : 0;
+}
+
+u_long
+IO_Close_Channel()
+{
+ todos_scclose(CT_ttyn);
+ CT_ttyn = -1;
+ CT_atrlen = 0;
+ return 0;
+}
+
+u_long
+IFD_Get_Capabilities(u_long Tag, u_char Value[])
+{
+ u_long r = IFD_ERROR_NOT_SUPPORTED;
+
+ switch (Tag) {
+ case 0x201:
+ r = 0;
+ break;
+ case SCTAG_IFD_CARDPRESENT:
+ *(u_long *) Value = todos_sccardpresent(CT_ttyn) ? IFD_ICC_PRESENT : IFD_ICC_NOT_PRESENT;
+ r = 0;
+ break;
+ case TAG_IFD_ATR:
+ memcpy(Value, CT_atr, CT_atrlen);
+ r = 0;
+ break;
+ case SCTAG_IFD_ATRLEN:
+ *(int *) Value = CT_atrlen;
+ r = 0;
+ break;
+ case TAG_OPEN_FLAGS:
+ *(int *) Value = cap_table[0].flags;
+ r = 0;
+ break;
+ case TAG_RESET_FLAGS:
+ *(int *) Value = cap_table[1].flags;
+ r = 0;
+ break;
+ }
+
+ return r;
+}
+
+/* NI:
+ set capabilities.
+ I take only one of two tags, that is, 0x800 (open flags) and
+ 0x801 (reset flags).
+
+ input: tag and the value.
+ output: if the tag is one of the two, set it, and return 0.
+ otherwise return NOT_SUPPORTED.
+*/
+
+u_long
+IFD_Set_Capabilities(u_long Tag, u_char Value[])
+{
+ int i;
+
+ for (i = 0 ; cap_table[i].tag != 0 ; i++ ) {
+ if (Tag == cap_table[i].tag) {
+ /* found the tag. set it. */
+ cap_table[i].flags = (int)*((int *)Value);
+#ifdef DEBUG
+ fprintf (stderr, "cap_table[%x].flags = %d\n",
+ Tag, cap_table[i].flags);
+#endif DEBUG
+
+ return 0;
+ }
+ }
+
+ return IFD_ERROR_NOT_SUPPORTED;
+}
+
+u_long
+IFD_Set_Protocol_Parameters(u_long ProtocolType, u_char SelectionFlags, u_char PTS1, u_char PTS2, u_char PTS3)
+{
+ return IFD_ERROR_NOT_SUPPORTED;
+}
+
+u_long
+IFD_Power_ICC(u_long a)
+{
+ u_long r;
+
+ if (a == IFD_POWER_UP)
+ r = (todos_scdtr(CT_ttyn, 1) < 0) ? IFD_ERROR_POWER_ACTION : 0;
+ else if (a == IFD_POWER_DOWN)
+ r = (todos_scdtr(CT_ttyn, 0) < 0) ? IFD_ERROR_POWER_ACTION : 0;
+ else if (a == IFD_RESET) {
+ CT_atrlen = todos_scxreset(CT_ttyn, cap_table[1].flags, CT_atr, NULL);
+ r = (CT_atrlen <= 0) ? IFD_ERROR_POWER_ACTION : 0;
+ } else
+ r = IFD_NOT_SUPPORTED;
+
+ return r;
+}
+
+u_long
+IFD_Swallow_ICC()
+{
+ return IFD_ERROR_NOT_SUPPORTED;
+}
+
+u_long
+IFD_Eject_ICC()
+{
+ return (todos_scdtr(CT_ttyn, 0) < 0) ? IFD_COMMUNICATION_ERROR : 0;
+}
+
+u_long
+IFD_Confiscate_ICC()
+{
+ return IFD_ERROR_NOT_SUPPORTED;
+}
+
+u_long
+IFD_Transmit_to_ICC(struct SCARD_IO_HEADER SendPci,
+ u_char ibuf[], u_long ilen, u_char obuf[], u_long *olen,
+ struct SCARD_IO_HEADER *RecvPci)
+{
+ unsigned char buf[255+2];
+ int n, p3, sw1, sw2;
+
+#ifdef DEBUG
+ printf("p3 %x ilen %x *olen %x\n", ibuf[4], ilen, *olen);
+#endif
+ ilen -= 5;
+
+ if (ilen > 0) {
+ /* "in" data; stupid ifd interface tacks le on the end */
+ if (ilen == ibuf[4] + 1) {
+ n = ibuf[5 + --ilen];
+#ifdef DEBUG
+ printf("found trailing le %d\n", n);
+#endif
+ } else if (*olen > 2)
+ n = sizeof buf;
+ else
+ n = 0;
+ } else
+ n = ibuf[4];
+
+ n = todos_scrw(CT_ttyn, ibuf[0], ibuf[1], ibuf[2], ibuf[3], ilen, &ibuf[5], n, buf, &sw1, &sw2);
+ if (n < 0)
+ return IFD_COMMUNICATION_ERROR;
+
+ if (n)
+ memcpy(obuf, buf, n);
+
+ obuf[n+0] = sw1;
+ obuf[n+1] = sw2;
+ *olen = n + 2;
+
+ return 0;
+}
+
+u_long
+IFD_Is_ICC_Present()
+{
+ return (todos_sccardpresent(CT_ttyn) ? IFD_ICC_PRESENT : IFD_ICC_NOT_PRESENT);
+}
+
+/*
+copyright 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/ifd/todos_ag/scT1.c b/lib/libsectok/ifd/todos_ag/scT1.c
new file mode 100644
index 00000000000..006f9da27fe
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/scT1.c
@@ -0,0 +1,172 @@
+/*
+ * T=1 protocol engine
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scT1.c,v 1.1 2001/05/22 15:35:57 rees Exp $";
+
+#ifdef __palmos__
+#include <Common.h>
+#include <System/SysAll.h>
+#include <System/MemoryMgr.h>
+#include <System/Unix/unix_stdlib.h>
+#include <System/Unix/sys_socket.h>
+#else
+#include <stdio.h>
+#endif
+#include <string.h>
+#ifdef TIMING
+#include <sys/time.h>
+#endif
+
+#include "todos_scrw.h"
+
+int
+todos_scioT1(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p)
+{
+ int i, len, n;
+ unsigned char *bp, *obp, tbuf[256];
+
+ /* Send 3 bytes prologue (7816-3 sec 9.4.1 fig 16) */
+
+ bp = tbuf;
+ len = 5 + ilen;
+
+ /* Send APDU */
+
+ *bp++ = cla;
+ *bp++ = ins;
+ *bp++ = p1;
+ *bp++ = p2;
+ *bp++ = ilen;
+
+ /* Send data */
+
+ for (i = 0; i < ilen; i++)
+ *bp++ = ibuf[i];
+#ifndef HUH
+ if (ilen) {
+ /* I don't understand this, but Visa card wants it */
+ *bp++ = 0;
+ len++;
+ }
+#endif
+
+ obp = obuf ? obuf : tbuf;
+
+ n = todos_scioT1Iblk(ttyn, len, tbuf, obp);
+
+ if (n >= 2) {
+ *sw1p = obp[n-2];
+ *sw2p = obp[n-1];
+ n -= 2;
+ }
+ return n;
+}
+
+int
+todos_scioT1Iblk(int ttyn, int ilen, unsigned char *ibuf, unsigned char *obuf)
+{
+ int n;
+ unsigned char tbuf[256];
+ static unsigned char ssn;
+
+ tbuf[0] = 0;
+ tbuf[1] = ssn;
+ ssn ^= 0x40;
+ tbuf[2] = ilen;
+ memcpy(&tbuf[3], ibuf, ilen);
+ n = todos_scioT1pkt(ttyn, tbuf, tbuf);
+ if (n < 0)
+ return n;
+ memcpy(obuf, &tbuf[3], tbuf[2]);
+ return tbuf[2];
+}
+
+int
+todos_scioT1pkt(int ttyn, unsigned char *ibuf, unsigned char *obuf)
+{
+ int i, len;
+ unsigned char edc, *bp;
+
+ len = ibuf[2] + 3;
+
+ /* Calculate checksum */
+
+ for (i = 0, edc = 0; i < len; i++)
+ edc ^= ibuf[i];
+ ibuf[len++] = edc;
+
+ /* Wait BGT = 22 etu */
+
+ todos_scsleep(scparam[ttyn].etu * 22 / 1000 + 1);
+
+ /* Send the packet */
+
+ todos_scputblk(ttyn, ibuf, len);
+
+ /* Read return packet */
+
+ bp = obuf;
+
+ /* Read three byte header */
+ for (i = 0; i < 3; i++) {
+ if (todos_scgetc(ttyn, bp++, (i == 0) ? scparam[ttyn].bwt : scparam[ttyn].cwt) != SCEOK) {
+#ifdef DEBUG
+ printf("T=1 header read timeout\n");
+#endif
+ return -1;
+ }
+ }
+ len = obuf[2];
+
+ /* Read data and edc */
+ for (i = 0; i < len + 1; i++) {
+ if (todos_scgetc(ttyn, bp++, scparam[ttyn].cwt) != SCEOK) {
+#ifdef DEBUG
+ printf("T=1 data read timeout\n");
+#endif
+ return -1;
+ }
+ }
+
+ /* Check edc */
+ for (i = 0, edc = 0; i < len + 3; i++)
+ edc ^= obuf[i];
+#ifdef DEBUG
+ if (edc != obuf[len + 3])
+ printf("edc mismatch, %02x != %02x\n", edc, obuf[len + 3]);
+#endif
+
+ return len;
+}
+
+/*
+copyright 1997, 1999, 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/ifd/todos_ag/scio.c b/lib/libsectok/ifd/todos_ag/scio.c
new file mode 100644
index 00000000000..e69a008b677
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/scio.c
@@ -0,0 +1,455 @@
+/*
+ * OS dependent part, Unix version
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scio.c,v 1.1 2001/05/22 15:35:57 rees Exp $";
+
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif /* _AIX */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include "todos_scrw.h"
+
+#ifdef __linux
+static char ttynametmpl[] = "/dev/cua%01d";
+#elif _AIX
+static char ttynametmpl[] = "/dev/tty%01d";
+#elif __OpenBSD__
+static char ttynametmpl[] = "/dev/cua%02d";
+#elif __sun
+/*static char ttynametmpl[] = "/dev/cua/%c";*/
+static char ttynametmpl[] = "/dev/tty%c";
+#else
+static char ttynametmpl[] = "/dev/tty%02d";
+#endif
+
+static struct {
+ int fd, flags, pid;
+ struct termios tio0, tio1;
+} sc[4];
+
+/* global variable */
+#ifdef BYTECOUNT
+int num_getc, num_putc;
+#endif /* BYTECOUNT */
+
+int
+todos_scopen(int ttyn, int flags, int *ep)
+{
+ char ttyname[32];
+ int fd, i, pid, oflags;
+
+#ifdef BYTECOUNT
+ num_getc = 0;
+ num_putc = 0;
+#endif /* BYTECOUNT */
+
+#ifdef __sun
+ sprintf(ttyname, ttynametmpl, 'a' + ttyn);
+#else
+ sprintf(ttyname, ttynametmpl, ttyn);
+#endif
+
+
+#ifdef DEBUG
+ printf ("ttyname=%s\n", ttyname);
+#endif /* DEBUG */
+ oflags = O_RDWR;
+ if (!(flags & SCODCD))
+ oflags |= O_NONBLOCK;
+ if ((fd = open(ttyname, oflags, 0)) < 0) {
+ if (ep)
+ *ep = SCENOTTY;
+ return -1;
+ }
+
+ if ((ttyn = todos_scfdopen(ttyn, fd, flags, ep)) < 0) {
+ close(fd);
+ return -2;
+ }
+
+ /* Figure out which reader we have */
+ if (ioctl(fd, TIOCMGET, &i) < 0) {
+ close(fd);
+ return 0;
+ }
+#ifndef __sun
+ /* Todos has RTS wired to RI, so set RTS and see if RI goes high */
+ i |= TIOCM_RTS;
+ ioctl(fd, TIOCMSET, &i);
+ ioctl(fd, TIOCMGET, &i);
+#else
+ /* Sun serial port is broken, has no RI line */
+ i = TIOCM_RI;
+#endif
+ if (i & TIOCM_RI) {
+ /* Todos reader */
+ todos_scsleep(20);
+ sc[ttyn].flags |= (SCOXCTS | SCOXDTR);
+ }
+
+ if (flags & SCODSR) {
+ /* Wait for card present */
+ while (!todos_sccardpresent(ttyn))
+ sleep(1);
+ }
+
+ if (flags & SCOHUP) {
+ /* spawn a process to wait for card removal */
+ pid = fork();
+ if (pid == 0) {
+ /* See if the card is still there */
+ while (todos_sccardpresent(ttyn))
+ sleep(1);
+ kill(getppid(), SIGHUP);
+ exit(0);
+ }
+ sc[ttyn].pid = pid;
+ }
+
+ return ttyn;
+}
+
+int
+todos_scsetflags(int ttyn, int flags, int mask)
+{
+ int oflags = sc[ttyn].flags;
+
+ sc[ttyn].flags &= ~mask;
+ sc[ttyn].flags |= (flags & mask);
+
+ if ((sc[ttyn].flags & SCOINVRT) != (oflags & SCOINVRT)) {
+ if (sc[ttyn].flags & SCOINVRT)
+ sc[ttyn].tio1.c_cflag |= PARODD;
+ else
+ sc[ttyn].tio1.c_cflag &= ~PARODD;
+ tcsetattr(sc[ttyn].fd, TCSADRAIN, &sc[ttyn].tio1);
+ }
+
+ return oflags;
+}
+
+/* NI: for Linux */
+#if (B9600 != 9600)
+struct speed_trans {
+ speed_t t_val;
+ int val;
+ char *s;
+} speed_trans[] = {
+ {0, 0, "a"},
+ {B9600, 9600, "a"},
+ {B19200, 19200, "a"},
+ {B38400, 38400, "a"},
+ {B57600, 55928, "a"},
+ {B57600, 57600, "a"},
+ {B115200, 115200, "a"},
+ {-1, -1, NULL}};
+#endif /* (B9600 != 9600) */
+
+int
+todos_scsetspeed(int ttyn, int speed)
+{
+
+#if (B9600 == 9600)
+ /* On OpenBSD, B9600 == 9600, and we can use the input argument
+ "speed" of this function as an argument to cfset[io]speed(). */
+#else
+ /* On Linux, B9600 != 9600, and we have to translate the input argument
+ to speed_t. */
+ int i;
+
+ for (i = 0; speed_trans[i].s; i++)
+ if (speed_trans[i].val == speed) break;
+ if (speed_trans[i].s == NULL) {
+ fprintf (stderr, "scsetspeed() failed : speed %d not supported. ignore ...\n",
+ speed);
+ return 0;
+ }
+ speed = speed_trans[i].t_val;
+#endif
+ cfsetispeed(&sc[ttyn].tio1, speed);
+ cfsetospeed(&sc[ttyn].tio1, speed);
+
+ return tcsetattr(sc[ttyn].fd, TCSADRAIN, &sc[ttyn].tio1);
+}
+
+int
+todos_scfdopen(int ttyn, int fd, int flags, int *ep)
+{
+ struct termios t;
+
+ /* Get and save the tty state */
+
+ if (tcgetattr(fd, &t) < 0) {
+ if (ep)
+ *ep = SCENOTTY;
+ return -1;
+ }
+ sc[ttyn].fd = fd;
+ sc[ttyn].tio0 = t;
+ sc[ttyn].flags = flags;
+
+ /* Now put the tty in a happy ISO state */
+
+ /* 9600 bps */
+ cfsetispeed(&t, B9600);
+ cfsetospeed(&t, B9600);
+
+ /* raw 8/E/2 */
+ t.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ t.c_iflag |= (IGNBRK|IGNPAR);
+ t.c_oflag &= ~OPOST;
+ t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+#ifdef CHWFLOW
+ t.c_cflag &= ~CHWFLOW;
+#endif
+#ifdef CRTSCTS
+ t.c_cflag &= ~CRTSCTS;
+#endif
+#ifdef CRTSXOFF
+ t.c_cflag &= ~CRTSXOFF;
+#endif
+ t.c_cflag |= CLOCAL;
+
+ /* 8/E/2 */
+ t.c_cflag &= ~(CSIZE | PARODD);
+ t.c_cflag |= (CS8 | PARENB | CSTOPB);
+
+ t.c_cc[VMIN] = 1;
+ t.c_cc[VTIME] = 0;
+
+ if (tcsetattr(fd, TCSANOW, &t) < 0) {
+ if (ep)
+ *ep = SCENOTTY;
+ sc[ttyn].fd = -1;
+ return -1;
+ }
+ sc[ttyn].tio1 = t;
+
+ /* The open may or may not have reset the card. Wait a while then flush
+ anything that came in on the port. */
+ todos_scsleep(250);
+ todos_scdrain(ttyn);
+
+ return ttyn;
+}
+
+/* find out if there is a card in the reader */
+
+int
+todos_sccardpresent(int ttyn)
+{
+ return (sc[ttyn].flags & SCOXCTS) ? !todos_sccts(ttyn) : todos_scdsr(ttyn);
+}
+
+/* query dsr on the port (usually indicates whether the card is present) */
+
+int
+todos_scdsr(int ttyn)
+{
+ int fd = sc[ttyn].fd;
+ int i;
+
+ if (fd < 0 || ioctl(fd, TIOCMGET, &i) < 0)
+ return 0;
+
+ return ((i & TIOCM_DSR) ? 1 : 0);
+}
+
+int
+todos_sccts(int ttyn)
+{
+ int fd = sc[ttyn].fd;
+ int i;
+
+ if (fd < 0 || ioctl(fd, TIOCMGET, &i) < 0)
+ return 0;
+
+ return ((i & TIOCM_CTS) ? 1 : 0);
+}
+
+/* raise or lower dtr */
+
+int
+todos_scdtr(int ttyn, int cmd)
+{
+ int fd = sc[ttyn].fd;
+ int i;
+
+ if (!todos_sccardpresent(ttyn))
+ return -1;
+
+ if (ioctl(fd, TIOCMGET, &i) < 0)
+ return -1;
+
+ if (cmd)
+ i |= TIOCM_DTR;
+ else
+ i &= ~TIOCM_DTR;
+ i |= TIOCM_RTS;
+
+ return ioctl(fd, TIOCMSET, &i);
+}
+
+int
+todos_scclose(int ttyn)
+{
+ int fd = sc[ttyn].fd;
+
+ tcsetattr(fd, TCSANOW, &sc[ttyn].tio0);
+ close(fd);
+ sc[ttyn].fd = -1;
+ if (sc[ttyn].pid) {
+ kill(sc[ttyn].pid, SIGTERM);
+ sc[ttyn].pid = 0;
+ }
+
+#ifdef BYTECOUNT
+ printf("#getc=%d, #putc=%d\n", num_getc - num_putc, num_putc);
+#endif /* BYTECOUNT */
+ return 0;
+}
+
+/*
+ * get one byte from the card.
+ * wait at most ms msec. 0 for poll, -1 for infinite.
+ * return byte in *cp.
+ * return 0 or error.
+ */
+
+int
+todos_scgetc(int ttyn, unsigned char *cp, int ms)
+{
+ int fd = sc[ttyn].fd;
+ fd_set fdset;
+ struct timeval tv, *tvp;
+
+#ifdef BYTECOUNT
+ num_getc++;
+#endif /* BYTECOUNT */
+
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ if (ms == -1)
+ tvp = NULL;
+ else {
+ tv.tv_sec = (ms + 1) / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
+ tvp = &tv;
+ }
+
+ if (select(fd + 1, &fdset, NULL, NULL, tvp) != 1)
+ return SCTIMEO;
+
+ if (read(fd, cp, 1) != 1)
+ return SCTIMEO;
+
+ if (sc[ttyn].flags & SCOINVRT)
+ *cp = scinvert[*cp];
+
+ return SCEOK; /* 0 */
+}
+
+/* write one byte to the card */
+
+int
+todos_scputc(int ttyn, int ic)
+{
+ int fd = sc[ttyn].fd;
+ unsigned char c0, c1;
+ int code;
+
+#ifdef BYTECOUNT
+ num_putc++;
+#endif /* BYTECOUNT */
+
+ c0 = (sc[ttyn].flags & SCOINVRT) ? scinvert[ic] : ic;
+ write(fd, &c0, 1);
+
+ /* gobble up the echo */
+ code = todos_scgetc(ttyn, &c1, 200);
+#ifdef GOBBLEDEBUG
+ if (sc[ttyn].flags & SCOINVRT)
+ c1 = scinvert[c1];
+ if (code)
+ printf("failed to gobble\n");
+ else if (c0 != c1)
+ printf("misgobbled %x != %x\n", c0, c1);
+ else
+ printf("gobble gobble %x\n", c0);
+#endif
+ return code;
+}
+
+int todos_scputblk(int ttyn, unsigned char *bp, int n)
+{
+ int fd = sc[ttyn].fd;
+ unsigned char c;
+
+ write(fd, bp, n);
+ while (n--)
+ todos_scgetc(ttyn, &c, 30);
+
+ return SCEOK;
+}
+
+void
+todos_scsleep(int ms)
+{
+ struct timeval tv;
+
+ if (!ms)
+ return;
+ tv.tv_sec = (ms + 1) / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
+
+ select(0, NULL, NULL, NULL, &tv);
+}
+
+void
+todos_scdrain(int ttyn)
+{
+ tcflush(sc[ttyn].fd, TCIFLUSH);
+}
+
+/*
+copyright 1997
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/ifd/todos_ag/scrw.c b/lib/libsectok/ifd/todos_ag/scrw.c
new file mode 100644
index 00000000000..0a4f5968370
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/scrw.c
@@ -0,0 +1,274 @@
+/*
+ * OS independent part
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scrw.c,v 1.1 2001/05/22 15:35:57 rees Exp $";
+
+#ifdef __palmos__
+#include <Common.h>
+#include <System/SysAll.h>
+#include <System/MemoryMgr.h>
+#include <System/Unix/unix_stdlib.h>
+#include <System/Unix/sys_socket.h>
+#else
+#include <stdio.h>
+#endif
+#include <string.h>
+#ifdef SCPERF
+#define SCPERF_FIRST_APPEARANCE
+#endif /* SCPERF */
+#include "todos_scrw.h"
+
+/* Global interface bytes */
+#define TA1 (tpb[0][0])
+#define TB1 (tpb[0][1])
+#define TC1 (tpb[0][2])
+#define TD1 (tpb[0][3])
+#define TC2 (tpb[1][2])
+#define TA2 (tpb[1][0])
+
+/* external variable */
+#ifdef BYTECOUNT
+extern int num_getc, num_putc;
+#endif /* BYTECOUNT */
+
+struct scparam scparam[4];
+
+#ifndef NO_T_EQ_1
+int todos_scioT1(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p);
+#endif
+
+/* reset the card, and return answer to reset (atr) */
+
+int
+todos_scxreset(int ttyn, int flags, unsigned char *atr, int *ep)
+{
+ unsigned char *ap, buf[33];
+ int n, err;
+
+ if (ep)
+ *ep = SCEOK;
+ else
+ ep = &err;
+
+ if (!todos_sccardpresent(ttyn)) {
+ *ep = SCENOCARD;
+ return 0;
+ }
+
+ if (!atr)
+ atr = buf;
+
+ if (!(flags & SCRTODOS) && (todos_scsetflags(ttyn, 0, 0) & SCOXDTR))
+ flags |= SCRTODOS;
+
+ todos_scsetspeed(ttyn, 9600);
+ todos_scsetflags(ttyn, 0, SCOINVRT);
+
+ if (todos_scdtr(ttyn, (flags & SCRTODOS)) < 0) {
+ *ep = SCENOCARD;
+ return 0;
+ }
+
+ /* 7816-3 sec 5.2 says >= 40000 clock cycles, ~=12 msec */
+ todos_scsleep(20);
+
+ todos_scdtr(ttyn, !(flags & SCRTODOS));
+
+ n = todos_get_atr(ttyn, flags, atr, &scparam[ttyn]);
+ if (!n && ep)
+ *ep = SCESLAG;
+ if (scparam[ttyn].t < 0 && ep)
+ *ep = SCENOSUPP;
+
+ return n;
+}
+
+static int
+todos_scioproc(int ttyn, int io, unsigned char *cp)
+{
+ int code;
+
+ /* Wait extra guard time if needed */
+ if (!io && scparam[ttyn].n)
+ todos_scsleep(((scparam[ttyn].n * scparam[ttyn].etu) + 999) / 1000);
+
+ code = (!io ? todos_scputc(ttyn, *cp) : todos_scgetc(ttyn, cp, scparam[ttyn].cwt));
+
+ return code;
+}
+
+/* This does the real work of transferring data to or from the card. Since the ack
+ handling is the same for both send and receive, we do it all here. */
+
+static int
+todos_scioT0(int ttyn, int io, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p)
+{
+ int n = 0, ack, ackxins;
+ unsigned char *bp = buf, c;
+#ifdef BYTECOUNT
+ int tmp_num_getc, tmp_num_putc;
+#endif /* BYTECOUNT */
+
+#ifdef BYTECOUNT
+ tmp_num_getc = num_getc;
+ tmp_num_putc = num_putc;
+#endif /* BYTECOUNT */
+
+#ifdef SCPERF
+ SetTime("SCIO starts");
+#endif /* SCPERF */
+
+#ifdef DEBUG
+ printf("scioT0 %3s %02x %02x %02x %02x %02x\n", io ? "out" : "in", cla, ins, p1, p2, p3);
+#endif
+
+ c = cla; todos_scioproc(ttyn, 0, &c);
+ c = ins; todos_scioproc(ttyn, 0, &c);
+ c = p1; todos_scioproc(ttyn, 0, &c);
+ c = p2; todos_scioproc(ttyn, 0, &c);
+ c = p3; todos_scioproc(ttyn, 0, &c);
+
+#ifdef SCPERF
+ SetTime("Finish sending APDU");
+#endif /* SCPERF */
+
+ while (1) {
+ /* read ack byte; see 7816-3 8.2.2 */
+ if (todos_scgetc(ttyn, &c, scparam[ttyn].cwt) != SCEOK) {
+#ifdef DEBUG
+ printf("%d ms timeout reading ack\n", scparam[ttyn].cwt);
+#endif
+ return -1;
+ }
+ ack = c;
+
+ if (ack == 0x60) {
+ /* null (no-op but resets timer) */
+#ifdef DEBUG
+ printf("got 0x60 (null) ack; reset timer\n");
+#endif
+ continue;
+ }
+
+ if ((ack & 0xf0) == 0x60 || (ack & 0xf0) == 0x90) {
+ /* SW1; get SW2 and return */
+ *sw1p = ack;
+ if (todos_scgetc(ttyn, &c, scparam[ttyn].cwt) != SCEOK) {
+#ifdef DEBUG
+ printf("%d ms timeout reading sw2\n", scparam[ttyn].cwt);
+#endif
+ return -1;
+ }
+ *sw2p = (c & 0xff);
+ break;
+ }
+
+ /* we would set VPP here if the interface supported it */
+
+ ackxins = (ack ^ ins) & 0xfe;
+ if (ackxins == 0xfe) {
+ /* xfer next data byte */
+ if (todos_scioproc(ttyn, io, bp++) != SCEOK) {
+#ifdef DEBUG
+ printf("%d ms timeout reading next data byte\n", scparam[ttyn].cwt);
+#endif
+ return -1;
+ }
+ n++;
+
+ } else if (ackxins == 0) {
+ /* xfer all remaining data bytes */
+ while (n < p3) {
+ if (todos_scioproc(ttyn, io, bp++) != SCEOK) {
+#ifdef DEBUG
+ printf("%d ms timeout reading all remaining data bytes\n", scparam[ttyn].cwt);
+#endif
+ return -1;
+ }
+ n++;
+ }
+#ifdef SCPERF
+ SetTime("Finish sending or receiving DATA");
+#endif /* SCPERF */
+ } else {
+ /* ?? unknown ack byte */
+#ifdef DEBUG
+ printf("unknown ack %x\n", ack);
+ continue;
+#else
+ return -1;
+#endif
+ }
+ }
+
+#ifdef SCPERF
+ SetTime("Finish scio");
+#endif /* SCPERF */
+
+#ifdef BYTECOUNT
+ tmp_num_putc = num_putc - tmp_num_putc;
+ tmp_num_getc = num_getc - tmp_num_getc - tmp_num_putc;
+ MESSAGE3("#getc=%d, #putc=%d\n", tmp_num_getc, tmp_num_putc);
+#endif /* BYTECOUNT */
+
+ return n;
+}
+
+int
+todos_scrw(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p)
+{
+ int r;
+
+ if (scparam[ttyn].t == 0) {
+ if (ilen > 0 && ibuf) {
+ /* Send "in" data */
+ r = (todos_scioT0(ttyn, 0, cla, ins, p1, p2, ilen, ibuf, sw1p, sw2p) >= 0) ? 0 : -1;
+ if (r >= 0 && *sw1p == 0x61 && olen >= *sw2p && obuf) {
+ /* Response available; get it */
+ r = todos_scioT0(ttyn, 1, cla, 0xc0, 0, 0, *sw2p, obuf, sw1p, sw2p);
+ }
+ } else {
+ /* Get "out" data */
+ r = todos_scioT0(ttyn, 1, cla, ins, p1, p2, olen, obuf, sw1p, sw2p);
+ }
+#ifndef NO_T_EQ_1
+ } else if (scparam[ttyn].t == 1) {
+ r = todos_scioT1(ttyn, cla, ins, p1, p2, ilen, ibuf, olen, obuf, sw1p, sw2p);
+#endif
+ } else
+ r = -1;
+
+ return r;
+}
+
+/*
+copyright 1997, 1999, 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/ifd/todos_ag/shlib_version b/lib/libsectok/ifd/todos_ag/shlib_version
new file mode 100644
index 00000000000..1edea46de91
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/shlib_version
@@ -0,0 +1,2 @@
+major=1
+minor=0
diff --git a/lib/libsectok/ifd/todos_ag/todos_scrw.h b/lib/libsectok/ifd/todos_ag/todos_scrw.h
new file mode 100644
index 00000000000..7a8bc326274
--- /dev/null
+++ b/lib/libsectok/ifd/todos_ag/todos_scrw.h
@@ -0,0 +1,170 @@
+/*
+ * $Id: todos_scrw.h,v 1.1 2001/05/22 15:35:57 rees Exp $
+ */
+
+/* SCPERF - performance evaluation */
+#ifdef SCPERF
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#endif /* SCPERF */
+
+/* open flags */
+#define SCODSR 0x1 /* wait for dsr */
+#define SCODCD 0x2 /* wait for dcd */
+#define SCOHUP 0x4 /* send signal on card removal */
+#define SCOXCTS 0x8 /* wait for no cts (todos reader) */
+#define SCOXDTR 0x10 /* invert dtr (todos reader) */
+#define SCOINVRT 0x20 /* inverse convention */
+
+/* Reset flags */
+#define SCRV 0x1 /* be verbose */
+#define SCRLEN 0x2 /* determine length by examing atr */
+#define SCRTODOS 0x4 /* Todos reader */
+#define SCRFORCE 0x8 /* Talk to card even if atr is bad */
+
+/* error codes */
+#define SCEOK 0
+#define SCENOTTY 1 /* no such tty */
+#define SCENOMEM 2 /* malloc (or similar) failed */
+#define SCTIMEO 3 /* time out */
+#define SCESLAG 4 /* slag (no atr) */
+#define SCENOSUPP 5 /* card type not supported */
+#define SCENOCARD 6 /* no card in reader */
+#define SCENOIMPL 7
+#define SCEDRVR 8
+#define SCECOMM 9
+#define SCECLOSED 10
+#define SCEUNKNOWN 11
+
+/* Extra tags for things they forgot to put in the ifd interface */
+#define SCTAG_IFD_ATRLEN 0x6601
+#define SCTAG_IFD_CARDPRESENT 0x301
+#define TAG_OPEN_FLAGS 0x800
+#define TAG_RESET_FLAGS 0x801
+
+extern struct scparam {
+ int t, etu, cwt, bwt, n;
+} scparam[];
+
+extern unsigned char scinvert[];
+
+/* forward declarations */
+
+int todos_scopen(int ttyn, int flags, int *ep);
+int todos_scsetflags(int ttyn, int flags, int mask);
+int todos_scrw(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p);
+int todos_sccardpresent(int ttyn);
+int todos_scdsr(int ttyn);
+int todos_scclose(int ttyn);
+int todos_scxreset(int ttyn, int flags, unsigned char *atr, int *ep);
+int todos_scdtr(int ttyn, int cmd);
+int todos_scgetc(int ttyn, unsigned char *cp, int ms);
+int todos_scputc(int ttyn, int ic);
+int todos_scputblk(int ttyn, unsigned char *bp, int n);
+void todos_scsleep(int ms);
+void todos_scdrain(int ttyn);
+int todos_scioT1(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p);
+int todos_scioT1Iblk(int ttyn, int ilen, unsigned char *ibuf, unsigned char *obuf);
+int todos_scioT1pkt(int ttyn, unsigned char *ibuf, unsigned char *obuf);
+int todos_get_atr(int ttyn, int flags, unsigned char *atr, struct scparam *param);
+
+/* SCPERF - performance evaluation */
+#ifdef SCPERF
+#ifdef SCPERF_FIRST_APPEARANCE
+
+#define MAX_EVENTS 1024
+
+struct timeval perf_tv[MAX_EVENTS];
+char *perf_buf[MAX_EVENTS];
+int perf_num = 0;
+
+void print_time ()
+{
+ int i;
+
+ for (i = 0 ; i < perf_num ; i ++ ) {
+ printf ("%d.%06d: %s\n",
+ perf_tv[i].tv_sec, perf_tv[i].tv_usec, perf_buf[i]);
+ }
+ return;
+}
+
+#define SetTime(x) \
+ gettimeofday(&(perf_tv[perf_num]), NULL); \
+ perf_buf[perf_num] = x; \
+ perf_num++; \
+ if (perf_num >= MAX_EVENTS) {\
+ fprintf (stderr, "SetTime overflow %d\n", MAX_EVENTS); \
+ exit (1); \
+ }
+
+#else /* !SCPERF_FIRST_APPEARANCE */
+extern struct timeval perf_tv[];
+extern char *perf_buf[];
+extern int perf_num;
+
+#define MAX_EVENTS 1024
+
+#define SetTime(x) \
+ gettimeofday(&(perf_tv[perf_num]), NULL); \
+ perf_buf[perf_num] = x; \
+ perf_num++; \
+ if (perf_num >= MAX_EVENTS) {\
+ fprintf (stderr, "SetTime overflow %d\n", MAX_EVENTS); \
+ exit (1); \
+ }
+#endif /* SCPERF_FIRST_APPEARANCE */
+
+#else /* !SCPERF */
+#define SetTime(x)
+#define print_time() ;
+#endif /* SCPERF */
+
+/* macros */
+#ifdef SCFS
+#define ADEBMISC 0x00000001 /* misc debugging */
+#define MESSAGE1(x) arla_warnx (ADEBMISC,x)
+#define MESSAGE2(x,y) arla_warnx (ADEBMISC,x,y)
+#define MESSAGE3(x,y,z) arla_warnx (ADEBMISC,x,y,z)
+#define MESSAGE4(x,y,z,u) arla_warnx (ADEBMISC,x,y,z,u)
+#define MESSAGE5(x,y,z,u,v) arla_warnx (ADEBMISC,x,y,z,u,v)
+#define MESSAGE6(x,y,z,u,v,w) arla_warnx (ADEBMISC,x,y,z,u,v,w)
+#else
+#define MESSAGE1(x) fprintf(stderr,x)
+#define MESSAGE2(x,y) fprintf(stderr,x,y)
+#define MESSAGE3(x,y,z) fprintf(stderr,x,y,z)
+#define MESSAGE4(x,y,z,u) fprintf(stderr,x,y,z,u)
+#define MESSAGE5(x,y,z,u,v) fprintf(stderr,x,y,z,u,v)
+#define MESSAGE6(x,y,z,u,v,w) fprintf(stderr,x,y,z,u,v,w)
+#endif /* SCFS */
+
+/*
+copyright 1997
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/Makefile b/lib/libsectok/lib/Makefile
new file mode 100644
index 00000000000..419a23c9abb
--- /dev/null
+++ b/lib/libsectok/lib/Makefile
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.1 2001/05/22 15:35:58 rees Exp $
+
+LIB= sectok
+SRCS= atr.c cmdtab.c input.c r1r2.c readers.c sc7816.c
+HDRS= sectok.h
+
+includes:
+ @cd ${.CURDIR}; for i in $(HDRS); do \
+ j="cmp -s $$i ${DESTDIR}/usr/include/`basename $$i` || \
+ ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m 444 $$i \
+ ${DESTDIR}/usr/include"; \
+ echo $$j; \
+ eval "$$j"; \
+ done
+
+.include <bsd.lib.mk>
diff --git a/lib/libsectok/lib/atr.c b/lib/libsectok/lib/atr.c
new file mode 100644
index 00000000000..c864010be57
--- /dev/null
+++ b/lib/libsectok/lib/atr.c
@@ -0,0 +1,348 @@
+/*
+ * Parse smart card atr, return proto params
+ *
+ * Jim Rees, University of Michigan CITI
+ */
+static char *rcsid = "$Id: atr.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#ifdef __palmos__
+#include <Common.h>
+#include <System/SysAll.h>
+#include <System/MemoryMgr.h>
+#include <System/Unix/unix_stdlib.h>
+#include <System/Unix/sys_socket.h>
+#else
+#include <stdio.h>
+#endif
+#include <string.h>
+
+#include "sectok.h"
+
+#ifdef __palmos__
+#undef printf
+#undef sprintf
+#define printf palmprintf
+#endif
+
+/* Global interface bytes */
+#define TA1 (tpb[0][0])
+#define TB1 (tpb[0][1])
+#define TC1 (tpb[0][2])
+#define TD1 (tpb[0][3])
+#define TC2 (tpb[1][2])
+#define TA2 (tpb[1][0])
+
+/* Inversion table, for inverse convention */
+unsigned char scinvert[] = {
+ 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
+ 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
+ 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17,
+ 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
+ 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b,
+ 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
+ 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13,
+ 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
+ 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
+ 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
+ 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15,
+ 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
+ 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19,
+ 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
+ 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11,
+ 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
+ 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e,
+ 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
+ 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16,
+ 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
+ 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a,
+ 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
+ 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12,
+ 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
+ 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c,
+ 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
+ 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
+ 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
+ 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18,
+ 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
+ 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10,
+ 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00,
+};
+
+/* 7816-3 1997 Table 7, 8 */
+static short Ftab[] = { 372, 372, 558, 744, 1116, 1488, 1860, -1,
+ -1, 512, 768, 1024, 1536, 2048, -1, -1 };
+static short Dtab[] = { -1, 1, 2, 4, 8, 16, 32, -1, 12, 20, -1, -1, -1, -1, -1, -1 };
+
+/*
+ * Table generated by mkFDtab.
+ */
+
+static struct bps {
+ unsigned char Fi, Di;
+ long bps;
+} bps[] = {
+ { 0x01, 0x08, 115464 },
+ { 0x09, 0x05, 111856 },
+ { 0x0b, 0x06, 111840 },
+ { 0x03, 0x08, 57732 },
+ { 0x09, 0x04, 55928 },
+ { 0x0a, 0x08, 55920 },
+ { 0x0b, 0x05, 55920 },
+ { 0x0d, 0x06, 55904 },
+ { 0x03, 0x04, 38488 },
+ { 0x01, 0x03, 38488 },
+ { 0x04, 0x08, 38484 },
+ { 0x06, 0x09, 38480 },
+ { 0x05, 0x05, 38480 },
+ { 0x0a, 0x04, 37280 },
+ { 0x0c, 0x05, 37280 },
+ { 0x05, 0x08, 28860 },
+ { 0x09, 0x03, 27964 },
+ { 0x0c, 0x08, 27960 },
+ { 0x0b, 0x04, 27960 },
+ { 0x0d, 0x05, 27952 },
+ { 0x06, 0x08, 23088 },
+ { 0x01, 0x02, 19244 },
+ { 0x03, 0x03, 19244 },
+ { 0x05, 0x04, 19240 },
+ { 0x0a, 0x03, 18640 },
+ { 0x0c, 0x04, 18640 },
+ { 0x09, 0x02, 13982 },
+ { 0x0b, 0x03, 13980 },
+ { 0x0d, 0x04, 13976 },
+ { 0x02, 0x02, 12828 },
+ { 0x04, 0x03, 12828 },
+ { 0, 0, 0 }
+};
+
+
+int
+parse_atr(int ttyn, int flags, unsigned char *atr, int len, struct scparam *param)
+{
+ int i, c, t, ts, t0, tck, nhb, pbn;
+ int F, D, Fi, Di, N, etu, WI;
+ unsigned char *ap, *hb;
+ unsigned char tpb[8][4];
+ int hiproto = 0;
+
+ ap = atr;
+
+ if (atr[0] == 0x3) {
+ if (flags & SCRV)
+ printf("inverse conversion\n");
+ for (i = 0; i < len; i++)
+ atr[i] = scinvert[atr[i]];
+#ifdef SCPPS
+ scsetflags(ttyn, SCOINVRT, SCOINVRT);
+#endif
+ }
+
+ ts = *ap++;
+
+ if (flags & SCRV) {
+ for (i = 0; i < len; i++)
+ printf("%d:%x ", i + 1, atr[i]);
+ printf("\n");
+ }
+
+ if (ts != 0x3b && ts != 0x3f) {
+ if (flags & SCRV)
+ printf("TS=%02x (not default timing)\n", ts);
+ param->t = -1;
+ return len;
+ }
+ t0 = *ap++;
+ nhb = t0 & 0xf;
+
+ /* Fill in defaults */
+ TA1 = 0x11;
+ TB1 = 0x4d;
+ TC1 = 0x00;
+ TC2 = 10;
+ TA2 = 0xff;
+ TD1 = 0;
+
+ Fi = 1;
+ Di = 1;
+
+ /* Get up to 8 sets of protocol bytes */
+ for (i = 0; i < 8; i++) {
+ tpb[i][3] = 0;
+ for (pbn = 0; pbn < 4; pbn++) {
+ /* If T0 (or TD(i)) indicates presence of proto byte, get it */
+ if (t0 & (1 << (4 + pbn)))
+ tpb[i][pbn] = *ap++;
+ }
+ t = tpb[i][3] & 0xf;
+ if (t > hiproto)
+ hiproto = t;
+
+ if (flags & SCRV) {
+ printf("proto %d T=%d", i + 1, t);
+ for (pbn = 0; pbn < 4; pbn++)
+ if (t0 & (1 << (4 + pbn)))
+ printf(" T%c%d=%02x", 'A' + pbn, i + 1, tpb[i][pbn]);
+ printf("\n");
+ }
+
+ t0 = tpb[i][3];
+ if (!(t0 & 0xf0))
+ break;
+ }
+
+ if (nhb) {
+ hb = ap;
+ ap += nhb;
+ }
+
+ if (nhb && (flags & SCRV)) {
+ printf("%d historical bytes:", nhb);
+ for (i = 0; i < nhb; i++) {
+ c = hb[i];
+ if (c >= ' ' && c <= '~')
+ printf(" %c", c);
+ else
+ printf(" %02x", c);
+ }
+ printf("\n");
+ }
+
+ if (hiproto > 0)
+ ap++;
+
+ if (ap - atr < len && (flags & SCRLEN))
+ len = ap - atr;
+
+ if (hiproto > 0) {
+ tck = 0;
+ for (i = 1; i < len; i++)
+ tck ^= atr[i];
+ if (tck != 0 && (flags & SCRV))
+ printf("Checksum failed, TCK=%x sum=%x\n", atr[len-1], tck);
+ }
+
+ /* got enough bytes? */
+
+ if (ap - atr != len && (flags & SCRV))
+ printf("expected %d proto bytes + %d historical bytes, got %d\n", ap - atr - nhb, nhb, len);
+ if (ap - atr > len) {
+ if (flags & SCRV)
+ printf("atr underrun\n");
+ param->t = -1;
+ return len;
+ }
+
+ /*
+ * I'm a little unclear on this. If TA2 is present, it indicates a specific mode.
+ * Else it's negotiable, and starts out with proto 1?
+ * 7816-3 6.6.1
+ */
+ if (TA2 != 0xff)
+ t = TA2 & 0xf;
+ else
+ t = TD1 & 0xf;
+
+ /* Todos reader won't do higher speeds */
+ if (!(flags & SCRTODOS)) {
+ for (i = 0; bps[i].bps; i++) {
+ if (((TA1 >> 4) & 0xf) >= bps[i].Fi && (TA1 & 0xf) >= bps[i].Di) {
+ int j;
+ unsigned char c;
+ static unsigned char pps[4] = {0xff, 0x10, 0, 0};
+
+ pps[2] = (bps[i].Fi << 4) | bps[i].Di;
+ pps[3] = 0;
+
+ if (flags & SCRV)
+ printf("speed %ld\n", bps[i].bps);
+
+#ifdef SCPPS
+ /* Compute checksum */
+ for (j = 0; j < 3; j++)
+ pps[3] ^= pps[j];
+
+ for (j = 0; j < 4; j++)
+ scputc(ttyn, pps[j]);
+ for (j = 0; j < 4; j++)
+ if (scgetc(ttyn, &c, 100) != SCEOK || c != pps[j])
+ break;
+ if (j != 4)
+ continue;
+ if (scsetspeed(ttyn, bps[i].bps) < 0) {
+ /* We already sent the pps, can't back out now, so fail. */
+ if (flags & SCRV)
+ printf("scsetspeed %ld failed\n", bps[i].bps);
+ param->t = -1;
+ return len;
+ }
+#endif
+ Fi = bps[i].Fi;
+ Di = bps[i].Di;
+ break;
+ }
+ }
+ }
+
+ F = Ftab[Fi];
+ D = Dtab[Di];
+ N = TC1;
+
+ /* 1/f = 1/3.579545 ~= 50/179; etu in microsec */
+ param->etu = etu = (F * 50L) / (D * 179L);
+ param->n = (N < 255) ? N : 0;
+
+ if (flags & SCRV) {
+ printf("%d etu = %d F / %d D * 3.58 f\n", etu, F, D);
+ if (N)
+ printf("%d N\n", N);
+ }
+
+ if (t == 0) {
+ WI = TC2;
+
+ /* cwt is in milliseconds */
+ param->cwt = (960L * WI * F) / 3580L;
+ if ((flags & SCRV) && WI != 10)
+ printf("%d cwt = (960 * %d WI * %d F) / 3.58 f / 1000\n",
+ param->cwt, WI, F);
+ } else if (t == 1) {
+ /* add 100 to each for engineering safety margin */
+ param->cwt = (11L + (1 << (TB1 & 0xf))) * etu / 1000 + 100;
+ param->bwt = (11L * etu / 1000L) + ((1 << ((TB1 >> 4) & 0xf)) * 100) + 100;
+ if (flags & SCRV)
+ printf("%d cwt, %d bwt\n", param->cwt, param->bwt);
+ }
+ param->t = t;
+
+ return len;
+}
+
+/*
+copyright 1997, 1999, 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/cmdtab.c b/lib/libsectok/lib/cmdtab.c
new file mode 100644
index 00000000000..f6cb21b431a
--- /dev/null
+++ b/lib/libsectok/lib/cmdtab.c
@@ -0,0 +1,140 @@
+static char *rcsid = "$Id: cmdtab.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#ifdef __palmos__
+#include <Common.h>
+#include <System/SysAll.h>
+#include <System/Unix/unix_stdio.h>
+#include <System/Unix/unix_stdlib.h>
+#include <System/Unix/sys_types.h>
+#include <string.h>
+#undef sprintf
+#undef vsprintf
+#else
+#include <stdio.h>
+#endif
+
+struct cmd {
+ int ins, inout;
+ char *name;
+} cmdtab[] = {
+ /* 7816-4 */
+ 0x0e, 0, "erase binary",
+ 0x20, 0, "verify",
+ 0x70, 0, "manage channel",
+ 0x82, 0, "ext auth",
+ 0x84, 1, "get challenge",
+ 0x88, 0, "int auth",
+ 0xa4, 0, "select",
+ 0xb0, 1, "read binary",
+ 0xb2, 1, "read record",
+ 0xc0, 1, "get response",
+ 0xc2, 0, "envelope",
+ 0xca, 0, "get data",
+ 0xd0, 0, "write binary",
+ 0xd2, 0, "write record",
+ 0xd6, 0, "update binary",
+ 0xda, 0, "put data",
+ 0xdc, 0, "update record",
+ 0xe2, 0, "append record",
+ /* Webcard */
+ 0xfe, 0, "ip7816",
+ /* Cyberflex Access */
+ 0x04, 0, "invalidate",
+ 0x08, 0, "manage instance",
+ 0x0a, 0, "manage program",
+ 0x0c, 0, "execute method",
+ 0x22, 0, "logout all",
+ 0x24, 0, "change PIN",
+ 0x2a, 0, "verify key",
+ 0x2c, 0, "unblock",
+ 0x44, 0, "rehabilitate",
+ 0xa8, 1, "directory",
+ 0xe0, 0, "create",
+ 0xe4, 0, "delete",
+ 0xfa, 0, "change java atr",
+ 0xfc, 0, "change acl",
+/* 0xfe, 1, "get acl",*/
+ /* GSM */
+ 0x26, 0, "disable PIN",
+ 0x28, 0, "enable PIN",
+ 0x30, 0, "decrease",
+ 0x32, 0, "increase",
+ 0xf2, 1, "get status",
+ /* Visa cash / open platform */
+ 0x50, 0, "init update",
+ 0x80, 0, "install default app",
+#ifdef PAYFLEX
+ /* Payflex */
+ 0x52, 0, "credit",
+ 0x54, 0, "debit",
+ 0x56, 0, "replace debit",
+ 0x58, 0, "token debit",
+ 0x5a, 0, "token purchase",
+ 0x5c, 0, "update currency",
+ 0x8a, 0, "cert credit",
+ 0x8c, 0, "cert debit",
+ 0x8e, 0, "generate diversified key",
+ 0xd8, 0, "load key",
+ 0xde, 0, "update max amount",
+ 0xf4, 0, "load exe",
+#endif /* PAYFLEX */
+ 0, 0, NULL
+};
+
+struct cmd *
+lookup_cmd(int ins)
+{
+ struct cmd *p;
+ static struct cmd dummy;
+ static char name[32];
+
+ for (p = &cmdtab[0]; p->name; p++)
+ if (p->ins == ins)
+ break;
+
+ if (!p->name) {
+ dummy.ins = ins;
+ dummy.inout = 2;
+ sprintf(name, "unknown ins %02x", ins);
+ dummy.name = name;
+ p = &dummy;
+ }
+
+ return p;
+}
+
+char *
+lookup_cmdname(int ins)
+{
+ return lookup_cmd(ins)->name;
+}
+
+/*
+copyright 1999
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/input.c b/lib/libsectok/lib/input.c
new file mode 100644
index 00000000000..b30db2b810e
--- /dev/null
+++ b/lib/libsectok/lib/input.c
@@ -0,0 +1,101 @@
+/*
+ * turn text into hex in a flexible way
+ *
+ * Jim Rees, University of Michigan, July 2000
+ */
+static char *rcsid = "$Id: input.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef TEST
+main(ac, av)
+int ac;
+char *av[];
+{
+ int i, n;
+ unsigned char obuf[256];
+
+ while (1) {
+ n = get_input(stdin, obuf, 1, sizeof obuf);
+ if (!n)
+ break;
+ for (i = 0; i < n; i++)
+ printf("%02x ", obuf[i]);
+ printf("\n");
+ }
+ exit(0);
+}
+#endif
+
+#ifndef __palmos__
+int
+get_input(FILE *f, unsigned char *obuf, int omin, int olen)
+{
+ int n = 0;
+ char ibuf[1024];
+
+ while (n < omin && fgets(ibuf, sizeof ibuf, f) != NULL)
+ n += parse_input(ibuf, obuf + n, olen - n);
+ return n;
+}
+#endif
+
+int
+parse_input(char *ibuf, unsigned char *obuf, int olen)
+{
+ char *cp;
+ unsigned char *up;
+ int its_hex, nhex, ntext, n, ndig;
+
+ if (!strncmp(ibuf, "0x", 2)) {
+ /* If it starts with '0x' it's hex */
+ ibuf += 2;
+ its_hex = 1;
+ } else if (ibuf[0] == '\"') {
+ /* If it starts with " it's text */
+ ibuf++;
+ its_hex = 0;
+ } else {
+ /* Count hex and non-hex characters */
+ nhex = ntext = 0;
+ for (cp = ibuf; *cp; cp++) {
+ if (isxdigit(*cp))
+ nhex++;
+ if (!isspace(*cp) && *cp != '.')
+ ntext++;
+ }
+
+ /*
+ * 1. Two characters is always text (scfs file names, for example)
+ * 2. Any non-space, non-hexdigit chars means it's text
+ */
+ if (ntext == 2 || ntext > nhex)
+ its_hex = 0;
+ else
+ its_hex = 1;
+ }
+
+ if (its_hex) {
+ for (cp = ibuf, up = obuf, n = ndig = 0; *cp && (up - obuf < olen); cp++) {
+ if (isxdigit(*cp)) {
+ n <<= 4;
+ n += isdigit(*cp) ? (*cp - '0') : ((*cp & 0x5f) - 'A' + 10);
+ }
+ if (ndig >= 1) {
+ *up++ = n;
+ n = 0;
+ ndig = 0;
+ } else if (isxdigit(*cp))
+ ndig++;
+ }
+ } else {
+ /* It's text */
+ for (cp = ibuf, up = obuf; *cp && (up - obuf < olen); cp++) {
+ if (isprint(*cp))
+ *up++ = *cp;
+ }
+ }
+
+ return (up - obuf);
+}
diff --git a/lib/libsectok/lib/r1r2.c b/lib/libsectok/lib/r1r2.c
new file mode 100644
index 00000000000..6452251d6ae
--- /dev/null
+++ b/lib/libsectok/lib/r1r2.c
@@ -0,0 +1,155 @@
+/* Return text for a given pair of sw1/sw2 status bytes */
+static char *rcsid = "$Id: r1r2.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#ifdef __palmos__
+#define NULL 0
+#define printf palmprintf
+#else
+#include <stdio.h>
+#endif
+
+#include "sectok.h"
+
+struct r1r2s {
+ int r1, r2;
+ char *s;
+} r1r2s[] = {
+ {0x90, 0x00, "ok"},
+ {0x61, 0xff, "ok; response available %x"},
+ {0x62, 0x34, "no such method"},
+ {0x62, 0x39, "out of memory"},
+ {0x62, 0x55, "null pointer"},
+ {0x62, 0x57, "array index out of bounds"},
+ {0x62, 0x58, "index out of bounds"},
+ {0x62, 0x81, "rec is corrupt"},
+ {0x62, 0x83, "invalid file"},
+ {0x63, 0x00, "auth failed"},
+ {0x63, 0x81, "invalid key"},
+ {0x67, 0xff, "invalid length; should be %x"},
+ {0x69, 0x80, "bad param"},
+ {0x69, 0x82, "unreadable"},
+ {0x69, 0x83, "auth method blocked"},
+ {0x69, 0x84, "data invalid"},
+ {0x69, 0x85, "no file selected"},
+ {0x69, 0x87, "busy/SM missing"},
+ {0x69, 0x88, "SM wrong"},
+ {0x6a, 0x80, "invalid file type"},
+ {0x6a, 0x81, "function not supported"},
+ {0x6a, 0x82, "file not found"},
+ {0x6a, 0x83, "no such rec"},
+ {0x6b, 0x00, "wrong mode"},
+ {0x6c, 0xff, "wrong length; should be %x"},
+ {0x6d, 0x00, "unknown instruction"},
+ {0x6e, 0x00, "wrong class"},
+ {0x6f, 0x14, "invalid applet state"},
+ {0x6f, 0x15, "invalid state"},
+ {0x6f, 0x19, "applet already running"},
+ {0x6f, 0xb0, "uninitialized key"},
+ {0x94, 0x81, "bad state"},
+ {0x00, 0x00, NULL}
+};
+
+#ifdef TEST
+main(int ac, char *av[])
+{
+ int r1, r2;
+ char *s;
+
+ if (ac != 3) {
+ fprintf(stderr, "usage: %s sw1 sw2 (in hex, please)\n", av[0]);
+ exit(1);
+ }
+ sscanf(av[1], "%x", &r1);
+ sscanf(av[2], "%x", &r2);
+ print_r1r2(r1, r2);
+ exit(0);
+}
+#endif
+
+void
+print_r1r2(int r1, int r2)
+{
+ printf("%s\n", get_r1r2s(r1, r2));
+}
+
+char *
+get_r1r2s(int r1, int r2)
+{
+ char *s;
+ static char buf[64];
+
+ s = scr1r2s(r1, r2);
+ if (s)
+ sprintf(buf, "%02x %02x %s", r1, r2, s);
+ else
+ sprintf(buf, "%02x %02x", r1, r2);
+ return buf;
+}
+
+char *
+scr1r2s(int r1, int r2)
+{
+ int i;
+ char *s;
+ static char buf[64];
+
+ for (i = 0; r1r2s[i].s; i++)
+ if (r1r2s[i].r1 == r1 && (r1r2s[i].r2 == r2 || r1r2s[i].r2 == 0xff))
+ break;
+ if (r1r2s[i].r2 != 0xff)
+ return r1r2s[i].s;
+ sprintf(buf, r1r2s[i].s, r2);
+ return buf;
+}
+
+#ifndef __palmos__
+int
+fdump_reply(FILE *f, unsigned char *p, int n, int r1, int r2)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ fprintf(f, "%d:%x ", i + 1, p[i]);
+ if (n)
+ fprintf(f, "\n");
+ if (r1)
+ fprintf(f, "%s\n", get_r1r2s(r1, r2));
+ return n;
+}
+
+int
+dump_reply(unsigned char *p, int n, int r1, int r2)
+{
+ fdump_reply(stdout, p, n, r1, r2);
+}
+#endif
+
+/*
+copyright 1999
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/readers.c b/lib/libsectok/lib/readers.c
new file mode 100644
index 00000000000..d10ef218026
--- /dev/null
+++ b/lib/libsectok/lib/readers.c
@@ -0,0 +1,53 @@
+/*
+ * parse the reader.conf file
+ *
+ * Jim Rees
+ * University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: readers.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+DBUpdateReaders(char *readerconf, void (callback) (char *name, unsigned long channelId, char *driverFile))
+{
+ FILE *f;
+ char buf[512], lv[64], rv[512], libpath[512];
+ long channelno;
+
+ f = fopen(readerconf, "r");
+ if (!f)
+ return -1;
+
+ libpath[0] = '\0';
+ channelno = -1;
+
+ while (fgets(buf, sizeof buf, f)) {
+ if (sscanf(buf, "%63s %511s", lv, rv) != 2)
+ continue;
+ if (rv[0] == '"') {
+ /* if rv starts with quote, read everything up to terminating quote */
+ sscanf(buf, "%*s \"%511[^\"]", rv);
+ }
+#ifdef DEBUG
+ printf("%s %s\n", lv, rv);
+#endif
+ if (!strcasecmp(lv, "libpath"))
+ strncpy(libpath, rv, sizeof libpath);
+ if (!strcasecmp(lv, "channelid"))
+ channelno = strtol(rv, NULL, 0);
+ if (libpath[0] && channelno != -1) {
+#ifdef DEBUG
+ printf("adding %x %s\n", channelno, libpath);
+#endif
+ (*callback)("", channelno, libpath);
+ libpath[0] = '\0';
+ channelno = -1;
+ }
+ }
+
+ fclose(f);
+ return 0;
+}
diff --git a/lib/libsectok/lib/sc7816.c b/lib/libsectok/lib/sc7816.c
new file mode 100644
index 00000000000..4a9dcb1632c
--- /dev/null
+++ b/lib/libsectok/lib/sc7816.c
@@ -0,0 +1,490 @@
+/*
+ * sc7816 library for use with pc/sc ifd drivers
+ *
+ * Jim Rees
+ * Mukesh Agrawal
+ * University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: sc7816.c,v 1.1 2001/05/22 15:35:58 rees Exp $";
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#ifdef SCPERF
+#define SCPERF_FIRST_APPEARANCE
+#endif /* SCPERF */
+
+#include "sectok.h"
+
+#define MAX_READERS 32
+
+/* pcsc cruft */
+#define MAX_ATR_SIZE 33
+#define IFD_ICC_PRESENT 615
+#define IFD_RESET 502
+#define TAG_IFD_ATR 0x303
+
+struct SCARD_IO_HEADER {
+ unsigned long Protocol, Length;
+};
+
+int DBUpdateReaders(char *readerconf, void (callback) (char *name, unsigned long channelId, char *driverFile));
+
+/* the callback for DBUpdateReaders */
+void addReader(char *name, unsigned long channelID, char *driverFile);
+
+int openReader(int readerNum, int flags);
+void *lookupSym(void *handle, char *name);
+
+typedef struct {
+ unsigned long channelID;
+ char *driverPath;
+ unsigned int driverLoaded;
+ /* for now, i'm only worry about the "bare essentials" */
+ long (*open)(unsigned long channelID);
+ long (*close)(void);
+ long (*data)(struct SCARD_IO_HEADER junk,
+ unsigned char *cmdData, unsigned long cmdLen,
+ unsigned char *respData, unsigned long *respLen,
+ struct SCARD_IO_HEADER *moreJunk);
+ long (*power)(unsigned long command);
+ long (*getcapa)(unsigned long selector, unsigned char *buffer);
+ long (*setcapa)(unsigned long selector, unsigned char *buffer);
+ long (*cardpresent)(void);
+} readerInfo;
+
+char *scerrtab[] = {
+ "ok",
+ "no such tty",
+ "out of memory",
+ "timeout",
+ "slag!",
+ "card type not supported",
+ "no card in reader",
+ "not implemented",
+ "error loading driver",
+ "communications error",
+ "reader not open",
+ "unknown error",
+};
+
+static char defaultConfigFilePath[] = "/etc/sectok.conf";
+
+unsigned int numReaders;
+readerInfo readers[MAX_READERS];
+
+/* NI, 11/1/2000 : Now the body of scopen() is in scxopen() to allow
+ specifing a path to the config file or the driver. scopen() is
+ an entry function for scxopen() to maintain backward compatibility. */
+int
+scopen(int ttyn, int flags, int *ep)
+{
+ return scxopen (ttyn, flags, ep, NULL, NULL);
+}
+
+/*
+ NI:
+
+ if (config_path != NULL and driver_name != NULL) error;
+ if (config_path != NULL) use sectok.conf there;
+ if (driver_path != NULL) use the specified driver;
+ if (config_path == NULL and driver_path == NULL) use /etc/sectok.conf;
+*/
+int
+scxopen(int ttyn, int flags, int *ep,
+ char *config_path, char *driver_path)
+{
+ int i, r;
+ static char todos_driver_path[] = "/usr/local/pcsc/lib/libtodos_ag.so";
+ char *configFilePath = defaultConfigFilePath;
+
+#ifdef SCPERF
+ SetTime ("scopen() start");
+#endif /* SCPERF */
+
+ if (config_path != NULL && driver_path != NULL) {
+ /* both config path and driver path are
+ specified. thus conflict. */
+ return SCECNFFILES;
+ }
+ else if (config_path != NULL) {
+ /* config file specified */
+ configFilePath = config_path;
+ }
+ else if (driver_path != NULL) {
+ /* driver path is specified */
+ numReaders = 0;
+
+ addReader(NULL, 0x10000, driver_path);
+ addReader(NULL, 0x10001, driver_path);
+
+ goto open_readers;
+ }
+
+ for (i = 0; i < numReaders; i++) {
+ if (readers[i].driverPath) {
+ free(readers[i].driverPath);
+ readers[i].driverPath = NULL;
+ }
+ }
+ numReaders = 0;
+
+ if (DBUpdateReaders(configFilePath, addReader) < 0) {
+ /* This usually means there is no sectok.conf. Supply a default. */
+ addReader(NULL, 0x10000, todos_driver_path);
+ addReader(NULL, 0x10001, todos_driver_path);
+ }
+
+ open_readers:
+ r = openReader(ttyn, flags);
+ if (ep)
+ *ep = r;
+
+ if (!r && (flags & SCODSR)) {
+ /* Wait for card present */
+ while (!sccardpresent(ttyn))
+ sleep(1);
+ }
+
+#ifdef SCPERF
+ SetTime ("scopen() end");
+#endif /* SCPERF */
+
+ return r ? -1 : ttyn;
+}
+
+int
+openReader(int readerNum, int flags)
+{
+ void *libHandle;
+ readerInfo *reader;
+
+#ifdef DEBUG
+ fprintf(stderr, "openReader %d\n", readerNum);
+#endif
+
+ if (readerNum < 0 || readerNum >= numReaders)
+ return SCEDRVR;
+ reader = &readers[readerNum];
+
+ if (!reader->driverLoaded) {
+ if (!reader->driverPath)
+ return SCEDRVR;
+ libHandle = dlopen(reader->driverPath, RTLD_LAZY);
+ if (!libHandle) {
+#ifdef DEBUG
+ fprintf(stderr, "%s: %s\n", reader->driverPath, dlerror());
+#endif
+ return SCEDRVR;
+ }
+ reader->open = lookupSym(libHandle, "IO_Create_Channel");
+ if (reader->open == NULL)
+ return SCEDRVR;
+
+ reader->close = lookupSym(libHandle, "IO_Close_Channel");
+ if (reader->close == NULL)
+ return SCEDRVR;
+
+ reader->data = lookupSym(libHandle, "IFD_Transmit_to_ICC");
+ if (reader->data == NULL)
+ return SCEDRVR;
+
+ reader->power = lookupSym(libHandle, "IFD_Power_ICC");
+ if (reader->power == NULL)
+ return SCEDRVR;
+
+ reader->getcapa = lookupSym(libHandle, "IFD_Get_Capabilities");
+ if (reader->getcapa == NULL)
+ return SCEDRVR;
+
+ reader->setcapa = lookupSym(libHandle, "IFD_Set_Capabilities");
+ if (reader->setcapa == NULL)
+ return SCEDRVR;
+
+ reader->cardpresent = lookupSym(libHandle, "IFD_Is_ICC_Present");
+
+ reader->driverLoaded = 1;
+ }
+
+ /* send flags to the driver */
+ reader->setcapa(TAG_OPEN_FLAGS, (u_char *)&flags);
+ /* if this returns an error, setcapa is not supported in this driver,
+ but that's OK. */
+
+ if (reader->open(reader->channelID))
+ return SCECOMM;
+ else
+ return 0;
+}
+
+int
+scclose(int readerNum)
+{
+ readerInfo *reader = &readers[readerNum];
+
+ if (reader->driverLoaded == 0)
+ return -1;
+
+ return (reader->close()) ? -1 : 0;
+}
+
+int
+sccardpresent(int ttyn)
+{
+ readerInfo *reader = &readers[ttyn];
+ unsigned long v;
+
+ if (!reader->driverLoaded)
+ return 0;
+
+ if (reader->cardpresent)
+ v = reader->cardpresent();
+ else if (reader->getcapa(SCTAG_IFD_CARDPRESENT, (unsigned char *) &v))
+ return 1;
+
+ return (v == IFD_ICC_PRESENT || v == 0) ? 1 : 0;
+}
+
+int
+scxreset(int ttyn, int flags, unsigned char *atr, int *ep)
+{
+ readerInfo *reader = &readers[ttyn];
+ int n = 0, r = SCEOK;
+ struct scparam param;
+
+#ifdef SCPERF
+ SetTime ("scxreset() start");
+#endif /* SCPERF */
+
+ if (reader->driverLoaded == 0) {
+ r = SCECLOSED;
+ goto out;
+ }
+
+ if (!sccardpresent(ttyn)) {
+ r = SCENOCARD;
+ goto out;
+ }
+
+ /* send flags to the driver */
+ reader->setcapa(TAG_RESET_FLAGS, (u_char *)&flags);
+ /* if this returns an error, setcapa is not supported in this driver,
+ but that's OK. */
+
+ if (reader->power(IFD_RESET)) {
+#ifdef DEBUG
+ fprintf(stderr, "power failed!\n");
+#endif
+ r = SCESLAG;
+ goto out;
+ }
+
+ if (atr && reader->getcapa(TAG_IFD_ATR, atr)) {
+#ifdef DEBUG
+ fprintf(stderr, "reset failed!\n");
+#endif
+ r = SCESLAG;
+ goto out;
+ }
+
+ if (reader->getcapa(SCTAG_IFD_ATRLEN, (unsigned char *) &n) || n <= 0) {
+ /* can't get atr len, take a wild guess */
+ if (atr) {
+ for (n = MAX_ATR_SIZE - 1; !atr[n]; n--)
+ ;
+ n--;
+ } else
+ n = MAX_ATR_SIZE;
+ }
+
+ if (flags & SCRV)
+ parse_atr(-1, flags, atr, n, &param);
+
+ out:
+ if (ep)
+ *ep = r;
+
+#ifdef SCPERF
+ SetTime ("scxreset() end");
+#endif /* SCPERF */
+
+ return n;
+}
+
+int
+screset(int ttyn, unsigned char *atr, int *ep)
+{
+ return scxreset(ttyn, 0, atr, ep);
+}
+
+int
+scrw(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p)
+{
+ unsigned char cmd[6+255], rsp[255+2];
+ unsigned long n;
+ int le;
+ readerInfo *reader = &readers[ttyn];
+ struct SCARD_IO_HEADER garbage;
+
+ if (reader->driverLoaded == 0)
+ return SCECLOSED;
+
+ cmd[0] = cla;
+ cmd[1] = ins;
+ cmd[2] = p1;
+ cmd[3] = p2;
+
+ ilen &= 0xff;
+ le = (255 < olen) ? 255 : olen;
+
+ if (ilen && ibuf) {
+ /* Send "in" data */
+ cmd[4] = ilen;
+ memcpy(&cmd[5], ibuf, ilen);
+ ilen += 5;
+ if (le)
+ cmd[ilen++] = le;
+ n = obuf ? sizeof rsp : 2;
+ if (reader->data(garbage, cmd, ilen, rsp, &n, NULL) || n < 2)
+ return -1;
+ if (rsp[n-2] == 0x61 && olen && obuf) {
+ /* Response available; get it (driver should do this but some don't) */
+ cmd[1] = 0xc0;
+ cmd[2] = cmd[3] = 0;
+ cmd[4] = rsp[n-1];
+ n = sizeof rsp;
+ if (reader->data(garbage, cmd, 5, rsp, &n, NULL))
+ return -1;
+ }
+ } else {
+ /* Get "out" data */
+ cmd[4] = olen;
+ n = sizeof rsp;
+ if (reader->data(garbage, cmd, 5, rsp, &n, NULL))
+ return -1;
+ }
+
+ if (n >= 2) {
+ *sw1p = rsp[n-2];
+ *sw2p = rsp[n-1];
+ n -= 2;
+ }
+
+ if (n && olen)
+ memcpy(obuf, rsp, (n < olen) ? n : olen);
+
+ return n;
+}
+
+int
+scwrite(int ttyn, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p)
+{
+ int rv;
+#ifdef SCPERF
+ char *scperf_buf;
+
+ scperf_buf = malloc (64);
+
+ sprintf (scperf_buf, "scwrite (ins %02x, p3 %02x) start", ins, p3);
+ SetTime(scperf_buf);
+
+ /* Ihis does not free scperf. It looks like memory leak ...
+ and it is, but it is actually the right behavior.
+ print_time() will print the messages later, so the buffer
+ must be there. */
+#endif /* SCPERF */
+ rv = scrw(ttyn, cla, ins, p1, p2, p3, buf, 0, NULL, sw1p, sw2p);
+
+#ifdef SCPERF
+ SetTime("scwrite() end");
+#endif /* SCPERF */
+ return (rv >= 0) ? p3 : -1;
+}
+
+int
+scread(int ttyn, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p)
+{
+ int rv;
+#ifdef SCPERF
+ char *scperf_buf;
+
+ scperf_buf = malloc (64);
+
+ sprintf (scperf_buf, "scread (ins %02x, p3 %02x) start", ins, p3);
+ SetTime(scperf_buf);
+
+ /* Ihis does not free scperf. It looks like memory leak ...
+ and it is, but it is actually the right behavior.
+ print_time() will print the messages later, so the buffer
+ must be there. */
+#endif /* SCPERF */
+ rv = scrw(ttyn, cla, ins, p1, p2, 0, NULL, p3, buf, sw1p, sw2p);
+
+#ifdef SCPERF
+ SetTime("scread() end");
+#endif /* SCPERF */
+ return rv;
+}
+
+void
+addReader(char *name, unsigned long channelID, char *driverFile)
+{
+ readerInfo *reader;
+
+ if (numReaders >= MAX_READERS)
+ return;
+
+ reader = &readers[numReaders++];
+
+ reader->channelID = channelID;
+ reader->driverPath = strdup(driverFile);
+ reader->driverLoaded = 0;
+}
+
+void *
+lookupSym(void *handle, char *name)
+{
+#ifdef __linux__
+ return dlsym(handle, name);
+#elif __sun
+ return dlsym(handle, name);
+#else
+ char undername[32];
+
+ sprintf(undername, "_%s", name);
+ return dlsym(handle, undername);
+#endif
+}
+
+/*
+copyright 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/sectok.h b/lib/libsectok/lib/sectok.h
new file mode 100644
index 00000000000..fe162b470af
--- /dev/null
+++ b/lib/libsectok/lib/sectok.h
@@ -0,0 +1,191 @@
+/*
+ * $Id: sectok.h,v 1.1 2001/05/22 15:35:58 rees Exp $
+ */
+
+/* SCPERF - performance evaluation */
+#ifdef SCPERF
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#endif /* SCPERF */
+
+/* open flags */
+#define SCODSR 0x1 /* wait for dsr */
+#define SCODCD 0x2 /* wait for dcd */
+#define SCOHUP 0x4 /* send signal on card removal */
+#define SCOXCTS 0x8 /* wait for no cts (todos reader) */
+#define SCOXDTR 0x10 /* invert dtr (todos reader) */
+#define SCOINVRT 0x20 /* inverse convention */
+
+/* Reset flags */
+#define SCRV 0x1 /* be verbose */
+#define SCRLEN 0x2 /* determine length by examing atr */
+#define SCRTODOS 0x4 /* Todos reader */
+#define SCRFORCE 0x8 /* Talk to card even if atr is bad */
+
+/* error codes */
+#define SCEOK 0
+#define SCENOTTY 1 /* no such tty */
+#define SCENOMEM 2 /* malloc (or similar) failed */
+#define SCTIMEO 3 /* time out */
+#define SCESLAG 4 /* slag (no atr) */
+#define SCENOSUPP 5 /* card type not supported */
+#define SCENOCARD 6 /* no card in reader */
+#define SCENOIMPL 7
+#define SCEDRVR 8
+#define SCECOMM 9
+#define SCECLOSED 10
+#define SCENOFILE 11 /* wrong config path or driver path */
+#define SCECNFFILES 12 /* both config path and driver path are
+ specified. thus conflict. */
+#define SCEUNKNOWN 13
+
+/* Extra tags for things they forgot to put in the ifd interface */
+#define SCTAG_IFD_ATRLEN 0x6601
+#define SCTAG_IFD_CARDPRESENT 0x301
+/* NI: flag passing */
+#define TAG_OPEN_FLAGS 0x800
+#define TAG_RESET_FLAGS 0x801
+
+extern char *scerrtab[];
+
+extern struct scparam {
+ int t, etu, cwt, bwt, n;
+} scparam[];
+
+/* forward declarations */
+
+int scopen(int ttyn, int flags, int *ep);
+int scxopen(int ttyn, int flags, int *ep,
+ char *config_path, char *driver_path);
+int scsetflags(int ttyn, int flags, int mask);
+int scrw(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p);
+int scread(int ttyn, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p);
+int scwrite(int ttyn, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p);
+int sccardpresent(int ttyn);
+int scdsr(int ttyn);
+int scclose(int ttyn);
+int screset(int ttyn, unsigned char *atr, int *ep);
+int scxreset(int ttyn, int flags, unsigned char *atr, int *ep);
+int scdtr(int ttyn, int cmd);
+int scgetc(int ttyn, unsigned char *cp, int ms);
+int scputc(int ttyn, int ic);
+int scgetblk(int ttyn, unsigned char *bp, int n, int bwt, int cwt);
+int scputblk(int ttyn, unsigned char *bp, int n);
+void scsleep(int ms);
+void scdrain(int ttyn);
+int scioT1(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p);
+int scioT1Iblk(int ttyn, int ilen, unsigned char *ibuf, unsigned char *obuf);
+int scioT1pkt(int ttyn, unsigned char *ibuf, unsigned char *obuf);
+int parse_atr(int ttyn, int flags, unsigned char *atr, int len, struct scparam *param);
+int parse_input(char *ibuf, unsigned char *obuf, int olen);
+#ifndef __palmos__
+int get_input(FILE *f, unsigned char *obuf, int omin, int olen);
+int fdump_reply(FILE *f, unsigned char *p, int n, int r1, int r2);
+int dump_reply(unsigned char *p, int n, int r1, int r2);
+#endif
+
+void print_r1r2(int r1, int r2);
+char *get_r1r2s(int r1, int r2);
+char *scr1r2s(int r1, int r2);
+char *lookup_cmdname(int ins);
+
+/* SCPERF - performance evaluation */
+#ifdef SCPERF
+#ifdef SCPERF_FIRST_APPEARANCE
+
+#define MAX_EVENTS 1024
+
+struct timeval perf_tv[MAX_EVENTS];
+char *perf_buf[MAX_EVENTS];
+int perf_num = 0;
+
+void print_time ()
+{
+ int i;
+
+ for (i = 0 ; i < perf_num ; i ++ ) {
+ printf ("%d.%06d: %s\n",
+ perf_tv[i].tv_sec, perf_tv[i].tv_usec, perf_buf[i]);
+ }
+ return;
+}
+
+#define SetTime(x) \
+ gettimeofday(&(perf_tv[perf_num]), NULL); \
+ perf_buf[perf_num] = x; \
+ perf_num++; \
+ if (perf_num >= MAX_EVENTS) {\
+ fprintf (stderr, "SetTime overflow %d\n", MAX_EVENTS); \
+ exit (1); \
+ }
+
+#else /* !SCPERF_FIRST_APPEARANCE */
+extern struct timeval perf_tv[];
+extern char *perf_buf[];
+extern int perf_num;
+
+#define MAX_EVENTS 1024
+
+#define SetTime(x) \
+ gettimeofday(&(perf_tv[perf_num]), NULL); \
+ perf_buf[perf_num] = x; \
+ perf_num++; \
+ if (perf_num >= MAX_EVENTS) {\
+ fprintf (stderr, "SetTime overflow %d\n", MAX_EVENTS); \
+ exit (1); \
+ }
+#endif /* SCPERF_FIRST_APPEARANCE */
+void print_time ();
+#else /* !SCPERF */
+#define SetTime(x)
+#define print_time() ;
+#endif /* SCPERF */
+
+/* macros */
+#ifdef SCFS
+#define ADEBMISC 0x00000001 /* misc debugging */
+#define MESSAGE1(x) arla_warnx (ADEBMISC,x)
+#define MESSAGE2(x,y) arla_warnx (ADEBMISC,x,y)
+#define MESSAGE3(x,y,z) arla_warnx (ADEBMISC,x,y,z)
+#define MESSAGE4(x,y,z,u) arla_warnx (ADEBMISC,x,y,z,u)
+#define MESSAGE5(x,y,z,u,v) arla_warnx (ADEBMISC,x,y,z,u,v)
+#define MESSAGE6(x,y,z,u,v,w) arla_warnx (ADEBMISC,x,y,z,u,v,w)
+#else
+#define MESSAGE1(x) fprintf(stderr,x)
+#define MESSAGE2(x,y) fprintf(stderr,x,y)
+#define MESSAGE3(x,y,z) fprintf(stderr,x,y,z)
+#define MESSAGE4(x,y,z,u) fprintf(stderr,x,y,z,u)
+#define MESSAGE5(x,y,z,u,v) fprintf(stderr,x,y,z,u,v)
+#define MESSAGE6(x,y,z,u,v,w) fprintf(stderr,x,y,z,u,v,w)
+#endif /* SCFS */
+
+/*
+copyright 1997, 2000
+the regents of the university of michigan
+all rights reserved
+
+permission is granted to use, copy, create derivative works
+and redistribute this software and such derivative works
+for any purpose, so long as the name of the university of
+michigan is not used in any advertising or publicity
+pertaining to the use or distribution of this software
+without specific, written prior authorization. if the
+above copyright notice or any other identification of the
+university of michigan is included in any copy of any
+portion of this software, then the disclaimer below must
+also be included.
+
+this software is provided as is, without representation
+from the university of michigan as to its fitness for any
+purpose, and without warranty by the university of
+michigan of any kind, either express or implied, including
+without limitation the implied warranties of
+merchantability and fitness for a particular purpose. the
+regents of the university of michigan shall not be liable
+for any damages, including special, indirect, incidental, or
+consequential damages, with respect to any claim arising
+out of or in connection with the use of the software, even
+if it has been or is hereafter advised of the possibility of
+such damages.
+*/
diff --git a/lib/libsectok/lib/shlib_version b/lib/libsectok/lib/shlib_version
new file mode 100644
index 00000000000..1edea46de91
--- /dev/null
+++ b/lib/libsectok/lib/shlib_version
@@ -0,0 +1,2 @@
+major=1
+minor=0