diff options
author | Jim Rees <rees@cvs.openbsd.org> | 2001-06-07 15:17:34 +0000 |
---|---|---|
committer | Jim Rees <rees@cvs.openbsd.org> | 2001-06-07 15:17:34 +0000 |
commit | e79bf55dc158d93c85332d7364cc081c5ed7f004 (patch) | |
tree | 0f156334f09069ae3055840248ec836e9d39d4cc /lib/libsectok | |
parent | be748640a8100f6e89cc57bac4fe6358cb57b868 (diff) |
libsectok for secure tokens (smartcard, iButton, etc)
Diffstat (limited to 'lib/libsectok')
-rw-r--r-- | lib/libsectok/Makefile | 17 | ||||
-rw-r--r-- | lib/libsectok/atr.c | 350 | ||||
-rw-r--r-- | lib/libsectok/cmdtab.c | 144 | ||||
-rw-r--r-- | lib/libsectok/ifdhandler.c | 262 | ||||
-rw-r--r-- | lib/libsectok/ifdhandler.h | 68 | ||||
-rw-r--r-- | lib/libsectok/input.c | 133 | ||||
-rw-r--r-- | lib/libsectok/r1r2.c | 159 | ||||
-rw-r--r-- | lib/libsectok/readers.c | 85 | ||||
-rw-r--r-- | lib/libsectok/sc7816.c | 504 | ||||
-rw-r--r-- | lib/libsectok/scT1.c | 175 | ||||
-rw-r--r-- | lib/libsectok/scio.c | 458 | ||||
-rw-r--r-- | lib/libsectok/scrw.c | 279 | ||||
-rw-r--r-- | lib/libsectok/sectok.h | 191 | ||||
-rw-r--r-- | lib/libsectok/shlib_version | 2 | ||||
-rw-r--r-- | lib/libsectok/todos_atr.c | 353 | ||||
-rw-r--r-- | lib/libsectok/todos_scrw.h | 57 |
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, ¶m); + + 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. +*/ |