summaryrefslogtreecommitdiff
path: root/lib/libsectok/atr.c
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/libsectok/atr.c
parentbe748640a8100f6e89cc57bac4fe6358cb57b868 (diff)
libsectok for secure tokens (smartcard, iButton, etc)
Diffstat (limited to 'lib/libsectok/atr.c')
-rw-r--r--lib/libsectok/atr.c350
1 files changed, 350 insertions, 0 deletions
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.
+*/