summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJim Rees <rees@cvs.openbsd.org>2001-06-07 15:17:34 +0000
committerJim Rees <rees@cvs.openbsd.org>2001-06-07 15:17:34 +0000
commite79bf55dc158d93c85332d7364cc081c5ed7f004 (patch)
tree0f156334f09069ae3055840248ec836e9d39d4cc /lib
parentbe748640a8100f6e89cc57bac4fe6358cb57b868 (diff)
libsectok for secure tokens (smartcard, iButton, etc)
Diffstat (limited to 'lib')
-rw-r--r--lib/libsectok/Makefile17
-rw-r--r--lib/libsectok/atr.c350
-rw-r--r--lib/libsectok/cmdtab.c144
-rw-r--r--lib/libsectok/ifdhandler.c262
-rw-r--r--lib/libsectok/ifdhandler.h68
-rw-r--r--lib/libsectok/input.c133
-rw-r--r--lib/libsectok/r1r2.c159
-rw-r--r--lib/libsectok/readers.c85
-rw-r--r--lib/libsectok/sc7816.c504
-rw-r--r--lib/libsectok/scT1.c175
-rw-r--r--lib/libsectok/scio.c458
-rw-r--r--lib/libsectok/scrw.c279
-rw-r--r--lib/libsectok/sectok.h191
-rw-r--r--lib/libsectok/shlib_version2
-rw-r--r--lib/libsectok/todos_atr.c353
-rw-r--r--lib/libsectok/todos_scrw.h57
16 files changed, 3233 insertions, 4 deletions
diff --git a/lib/libsectok/Makefile b/lib/libsectok/Makefile
index 41636cd49d6..51b0856467d 100644
--- a/lib/libsectok/Makefile
+++ b/lib/libsectok/Makefile
@@ -1,7 +1,16 @@
-# $OpenBSD: Makefile,v 1.1 2001/05/22 15:35:56 rees Exp $
+# $OpenBSD: Makefile,v 1.2 2001/06/07 15:17:32 rees Exp $
-.include <bsd.own.mk>
+LIB= sectok
+SRCS= atr.c cmdtab.c input.c r1r2.c sc7816.c todos_atr.c ifdhandler.c scT1.c scio.c scrw.c
+HDRS= sectok.h
-SUBDIR= lib ifd
+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.subdir.mk>
+.include <bsd.lib.mk>
diff --git a/lib/libsectok/atr.c b/lib/libsectok/atr.c
new file mode 100644
index 00000000000..618ba4b7b19
--- /dev/null
+++ b/lib/libsectok/atr.c
@@ -0,0 +1,350 @@
+/*
+ * Parse smart card atr, return proto params
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan CITI
+ */
+static char *rcsid = "$Id: atr.c,v 1.1 2001/06/07 15:17:32 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, 2001
+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/cmdtab.c b/lib/libsectok/cmdtab.c
new file mode 100644
index 00000000000..5985ee11cd6
--- /dev/null
+++ b/lib/libsectok/cmdtab.c
@@ -0,0 +1,144 @@
+/*
+ * See copyright notice at end of file
+ */
+
+static char *rcsid = "$Id: cmdtab.c,v 1.1 2001/06/07 15:17:32 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/ifdhandler.c b/lib/libsectok/ifdhandler.c
new file mode 100644
index 00000000000..296e8a60e12
--- /dev/null
+++ b/lib/libsectok/ifdhandler.c
@@ -0,0 +1,262 @@
+/*
+ * IFD handler for CITI sc7816 dumb reader driver
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: ifdhandler.c,v 1.1 2001/06/07 15:17:32 rees Exp $";
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <string.h>
+
+#include "sectok.h"
+#include "todos_scrw.h"
+#include "ifdhandler.h"
+
+/* capability table */
+struct cap_entry {
+ u_long tag;
+ int flags;
+} cap_table[] = {
+ {SCTAG_OPEN_FLAGS, 0}, /* open flags */
+ {SCTAG_RESET_FLAGS, 0}, /* reset flags */
+ {0, 0} /* terminator */
+};
+
+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 SCTAG_OPEN_FLAGS:
+ *(int *) Value = cap_table[0].flags;
+ r = 0;
+ break;
+ case SCTAG_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/ifdhandler.h b/lib/libsectok/ifdhandler.h
new file mode 100644
index 00000000000..8d148a560fd
--- /dev/null
+++ b/lib/libsectok/ifdhandler.h
@@ -0,0 +1,68 @@
+/*
+ * pcsc cruft
+ *
+ * See copyright notice at end of file
+ *
+ * $Id: ifdhandler.h,v 1.1 2001/06/07 15:17:32 rees Exp $
+ */
+
+#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;
+};
+
+/* IFD interface */
+u_long IO_Create_Channel(u_long ChannelId);
+u_long IO_Close_Channel();
+u_long IFD_Get_Capabilities(u_long Tag, u_char Value[]);
+u_long IFD_Set_Capabilities(u_long Tag, u_char Value[]);
+u_long IFD_Set_Protocol_Parameters(u_long ProtocolType, u_char SelectionFlags, u_char PTS1, u_char PTS2, u_char PTS3);
+u_long IFD_Power_ICC(u_long a);
+u_long IFD_Swallow_ICC();
+u_long IFD_Eject_ICC();
+u_long IFD_Confiscate_ICC();
+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);
+u_long IFD_Is_ICC_Present();
+
+/*
+copyright 2001
+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/input.c b/lib/libsectok/input.c
new file mode 100644
index 00000000000..df0043238a6
--- /dev/null
+++ b/lib/libsectok/input.c
@@ -0,0 +1,133 @@
+/*
+ * turn text into hex in a flexible way
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan, July 2000
+ */
+static char *rcsid = "$Id: input.c,v 1.1 2001/06/07 15:17:33 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);
+}
+
+/*
+copyright 2001
+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/r1r2.c b/lib/libsectok/r1r2.c
new file mode 100644
index 00000000000..c9c4c075c95
--- /dev/null
+++ b/lib/libsectok/r1r2.c
@@ -0,0 +1,159 @@
+/*
+ * Return text for a given pair of sw1/sw2 status bytes
+ *
+ * See copyright notice at end of file
+ */
+static char *rcsid = "$Id: r1r2.c,v 1.1 2001/06/07 15:17:33 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/readers.c b/lib/libsectok/readers.c
new file mode 100644
index 00000000000..2818e9e9e5b
--- /dev/null
+++ b/lib/libsectok/readers.c
@@ -0,0 +1,85 @@
+/*
+ * parse the reader.conf file
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees
+ * University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: readers.c,v 1.1 2001/06/07 15:17:33 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;
+}
+
+/*
+copyright 2001
+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/sc7816.c b/lib/libsectok/sc7816.c
new file mode 100644
index 00000000000..8b0464f3667
--- /dev/null
+++ b/lib/libsectok/sc7816.c
@@ -0,0 +1,504 @@
+/*
+ * sc7816 library for use with pc/sc ifd drivers
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees
+ * Mukesh Agrawal
+ * University of Michigan CITI, August 2000
+ */
+static char *rcsid = "$Id: sc7816.c,v 1.1 2001/06/07 15:17:33 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"
+#include "ifdhandler.h"
+
+#define MAX_READERS 32
+
+#ifdef DL_READERS
+static char defaultConfigFilePath[] = "/etc/reader.conf";
+
+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);
+void *lookupSym(void *handle, char *name);
+#endif
+
+int openReader(int readerNum, int flags);
+
+typedef struct {
+ unsigned long channelID;
+ char *driverPath;
+ unsigned int driverLoaded;
+ /* for now, i'm only worry about the "bare essentials" */
+ u_long (*open)(unsigned long channelID);
+ u_long (*close)(void);
+ u_long (*data)(struct SCARD_IO_HEADER junk,
+ unsigned char *cmdData, unsigned long cmdLen,
+ unsigned char *respData, unsigned long *respLen,
+ struct SCARD_IO_HEADER *moreJunk);
+ u_long (*power)(unsigned long command);
+ u_long (*getcapa)(unsigned long selector, unsigned char *buffer);
+ u_long (*setcapa)(unsigned long selector, unsigned char *buffer);
+ u_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",
+};
+
+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 reader.conf there;
+ if (driver_path != NULL) use the specified driver;
+ if (config_path == NULL and driver_path == NULL) use /etc/reader.conf;
+*/
+int
+scxopen(int ttyn, int flags, int *ep,
+ char *config_path, char *driver_path)
+{
+ int i, r;
+#ifdef DL_READERS
+ static char todos_driver_path[] = "/usr/local/pcsc/lib/libtodos_ag.so";
+ char *configFilePath = defaultConfigFilePath;
+#endif
+
+#ifdef SCPERF
+ SetTime ("scopen() start");
+#endif /* SCPERF */
+
+#ifdef DL_READERS
+ 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 reader.conf. Supply a default. */
+ addReader(NULL, 0x10000, todos_driver_path);
+ addReader(NULL, 0x10001, todos_driver_path);
+ }
+#else
+ numReaders = 4;
+#endif
+
+ 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) {
+#ifdef DL_READERS
+ 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");
+#else /* DL_READERS */
+ reader->open = IO_Create_Channel;
+ reader->close = IO_Close_Channel;
+ reader->data = IFD_Transmit_to_ICC;
+ reader->power = IFD_Power_ICC;
+ reader->getcapa = IFD_Get_Capabilities;
+ reader->setcapa = IFD_Set_Capabilities;
+ reader->cardpresent = IFD_Is_ICC_Present;
+ reader->channelID = (0x10000 | readerNum);
+#endif /* DL_READERS */
+
+ reader->driverLoaded = 1;
+ }
+
+ /* send flags to the driver */
+ reader->setcapa(SCTAG_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(SCTAG_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;
+}
+
+#ifdef DL_READERS
+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
+}
+#endif /* DL_READERS */
+
+/*
+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/scT1.c b/lib/libsectok/scT1.c
new file mode 100644
index 00000000000..7398a3ef110
--- /dev/null
+++ b/lib/libsectok/scT1.c
@@ -0,0 +1,175 @@
+/*
+ * T=1 protocol engine
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scT1.c,v 1.1 2001/06/07 15:17:33 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 "sectok.h"
+#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/scio.c b/lib/libsectok/scio.c
new file mode 100644
index 00000000000..8d5ee9cd9d6
--- /dev/null
+++ b/lib/libsectok/scio.c
@@ -0,0 +1,458 @@
+/*
+ * OS dependent part, Unix version
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scio.c,v 1.1 2001/06/07 15:17:33 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 "sectok.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 = todos_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) ? todos_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 = todos_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/scrw.c b/lib/libsectok/scrw.c
new file mode 100644
index 00000000000..57180c34954
--- /dev/null
+++ b/lib/libsectok/scrw.c
@@ -0,0 +1,279 @@
+/*
+ * OS independent part
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan, October 1997
+ */
+static char *rcsid = "$Id: scrw.c,v 1.1 2001/06/07 15:17:33 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/unix_string.h>
+#include <UI/UIAll.h>
+#include "field.h"
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+#ifdef SCPERF
+#define SCPERF_FIRST_APPEARANCE
+#endif /* SCPERF */
+#include "sectok.h"
+#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/sectok.h b/lib/libsectok/sectok.h
new file mode 100644
index 00000000000..b1e487a73b6
--- /dev/null
+++ b/lib/libsectok/sectok.h
@@ -0,0 +1,191 @@
+/*
+ * See copyright notice at end of file
+ *
+ * $Id: sectok.h,v 1.1 2001/06/07 15:17:33 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
+#define SCTAG_OPEN_FLAGS 0x800
+#define SCTAG_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/shlib_version b/lib/libsectok/shlib_version
new file mode 100644
index 00000000000..1edea46de91
--- /dev/null
+++ b/lib/libsectok/shlib_version
@@ -0,0 +1,2 @@
+major=1
+minor=0
diff --git a/lib/libsectok/todos_atr.c b/lib/libsectok/todos_atr.c
new file mode 100644
index 00000000000..151428fb13f
--- /dev/null
+++ b/lib/libsectok/todos_atr.c
@@ -0,0 +1,353 @@
+/*
+ * Parse smart card atr, return proto params
+ *
+ * See copyright notice at end of file
+ *
+ * Jim Rees, University of Michigan CITI
+ */
+static char *rcsid = "$Id: todos_atr.c,v 1.1 2001/06/07 15:17:33 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/unix_string.h>
+#include <UI/UIAll.h>
+#include "field.h"
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "sectok.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 todos_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 = todos_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/todos_scrw.h b/lib/libsectok/todos_scrw.h
new file mode 100644
index 00000000000..65a6366f28b
--- /dev/null
+++ b/lib/libsectok/todos_scrw.h
@@ -0,0 +1,57 @@
+/*
+ * See copyright notice at end of file
+ *
+ * $Id: todos_scrw.h,v 1.1 2001/06/07 15:17:33 rees Exp $
+ */
+
+extern unsigned char todos_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);
+
+/*
+copyright 1997, 2001
+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.
+*/