1 /* $Id: atr.c,v 1.3 2001/08/02 23:15:39 rees Exp rees $ */
2 
3 /*
4 copyright 1997, 1999, 2000, 2001
5 the regents of the university of michigan
6 all rights reserved
7 
8 permission is granted to use, copy, create derivative works
9 and redistribute this software and such derivative works
10 for any purpose, so long as the name of the university of
11 michigan is not used in any advertising or publicity
12 pertaining to the use or distribution of this software
13 without specific, written prior authorization.  if the
14 above copyright notice or any other identification of the
15 university of michigan is included in any copy of any
16 portion of this software, then the disclaimer below must
17 also be included.
18 
19 this software is provided as is, without representation
20 from the university of michigan as to its fitness for any
21 purpose, and without warranty by the university of
22 michigan of any kind, either express or implied, including
23 without limitation the implied warranties of
24 merchantability and fitness for a particular purpose. the
25 regents of the university of michigan shall not be liable
26 for any damages, including special, indirect, incidental, or
27 consequential damages, with respect to any claim arising
28 out of or in connection with the use of the software, even
29 if it has been or is hereafter advised of the possibility of
30 such damages.
31 */
32 
33 /*
34  * Parse smart card atr, return proto params
35  *
36  * Jim Rees, University of Michigan CITI
37  */
38 
39 #ifdef __palmos__
40 #include <Common.h>
41 #include <System/SysAll.h>
42 #include <System/Unix/unix_stdlib.h>
43 #include <System/Unix/unix_string.h>
44 #include <UI/UIAll.h>
45 #include "field.h"
46 typedef long int32_t;
47 #else
48 #include <sys/types.h>
49 #include <stdio.h>
50 #include <string.h>
51 #endif
52 
53 #include "sectok.h"
54 
55 /* Global interface bytes */
56 #define TA1 (tpb[0][0])
57 #define TB1 (tpb[0][1])
58 #define TC1 (tpb[0][2])
59 #define TD1 (tpb[0][3])
60 #define TC2 (tpb[1][2])
61 #define TA2 (tpb[1][0])
62 
63 /* Inversion table, for inverse convention */
64 unsigned char scinvert[] = {
65     0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f,
66     0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
67     0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17,
68     0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
69     0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b,
70     0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
71     0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13,
72     0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
73     0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
74     0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
75     0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15,
76     0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
77     0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19,
78     0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
79     0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11,
80     0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
81     0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e,
82     0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
83     0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16,
84     0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
85     0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a,
86     0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
87     0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12,
88     0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
89     0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c,
90     0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
91     0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
92     0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
93     0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18,
94     0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
95     0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10,
96     0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00,
97 };
98 
99 /* 7816-3 1997 Table 7, 8 */
100 static short Ftab[] = { 372, 372, 558,  744, 1116, 1488, 1860, -1,
101 		  -1, 512, 768, 1024, 1536, 2048,   -1, -1 };
102 static short Dtab[] = { -1, 1, 2, 4, 8, 16, 32, -1, 12, 20, -1, -1, -1, -1, -1, -1 };
103 
104 /*
105  * Table generated by mkFDtab.
106  */
107 
108 static struct bps {
109     unsigned char Fi, Di;
110     int32_t bps;
111 } bps[] = {
112     { 0x01, 0x08, 115464 },
113     { 0x09, 0x05, 111856 },
114     { 0x0b, 0x06, 111840 },
115     { 0x03, 0x08,  57732 },
116     { 0x09, 0x04,  55928 },
117     { 0x0a, 0x08,  55920 },
118     { 0x0b, 0x05,  55920 },
119     { 0x0d, 0x06,  55904 },
120     { 0x03, 0x04,  38488 },
121     { 0x01, 0x03,  38488 },
122     { 0x04, 0x08,  38484 },
123     { 0x06, 0x09,  38480 },
124     { 0x05, 0x05,  38480 },
125     { 0x0a, 0x04,  37280 },
126     { 0x0c, 0x05,  37280 },
127     { 0x05, 0x08,  28860 },
128     { 0x09, 0x03,  27964 },
129     { 0x0c, 0x08,  27960 },
130     { 0x0b, 0x04,  27960 },
131     { 0x0d, 0x05,  27952 },
132     { 0x06, 0x08,  23088 },
133     { 0x01, 0x02,  19244 },
134     { 0x03, 0x03,  19244 },
135     { 0x05, 0x04,  19240 },
136     { 0x0a, 0x03,  18640 },
137     { 0x0c, 0x04,  18640 },
138     { 0x09, 0x02,  13982 },
139     { 0x0b, 0x03,  13980 },
140     { 0x0d, 0x04,  13976 },
141     { 0x02, 0x02,  12828 },
142     { 0x04, 0x03,  12828 },
143     { 0, 0, 0 }
144 };
145 
146 
147 int
sectok_parse_atr(int ttyn,int flags,unsigned char * atr,int len,struct scparam * param)148 sectok_parse_atr(int ttyn, int flags, unsigned char *atr, int len, struct scparam *param)
149 {
150     int i, c, t, ts, t0, tck, nhb, pbn;
151     int F, D, Fi, Di, N, etu, WI;
152     unsigned char *ap, *hb;
153     unsigned char tpb[8][4];
154     int hiproto = 0;
155 
156     ap = atr;
157 
158     if (atr[0] == 0x3) {
159 	if (flags & STRV)
160 	    printf("inverse conversion\n");
161 	for (i = 0; i < len; i++)
162 	    atr[i] = scinvert[atr[i]];
163     }
164 
165     ts = *ap++;
166 
167     if (flags & STRV) {
168 	for (i = 0; i < len; i++)
169 	    printf("%d:%x ", i + 1, atr[i]);
170 	printf("\n");
171     }
172 
173     if (ts != 0x3b && ts != 0x3f) {
174 	if (flags & STRV)
175 	    printf("TS=%02x (not default timing)\n", ts);
176 	param->t = -1;
177 	return len;
178     }
179     t0 = *ap++;
180     nhb = t0 & 0xf;
181 
182     /* Fill in defaults */
183     TA1 = 0x11;
184     TB1 = 0x4d;
185     TC1 = 0x00;
186     TC2 = 10;
187     TA2 = 0xff;
188     TD1 = 0;
189 
190     Fi = 1;
191     Di = 1;
192 
193     /* Get up to 8 sets of protocol bytes */
194     for (i = 0; i < 8; i++) {
195 	tpb[i][3] = 0;
196 	for (pbn = 0; pbn < 4; pbn++) {
197 	    /* If T0 (or TD(i)) indicates presence of proto byte, get it */
198 	    if (t0 & (1 << (4 + pbn)))
199 		tpb[i][pbn] = *ap++;
200 	}
201 	t = tpb[i][3] & 0xf;
202 	if (t > hiproto)
203 	    hiproto = t;
204 
205 	if (flags & STRV) {
206 	    printf("proto %d T=%d", i + 1, t);
207 	    for (pbn = 0; pbn < 4; pbn++)
208 		if (t0 & (1 << (4 + pbn)))
209 		    printf(" T%c%d=%02x", 'A' + pbn, i + 1, tpb[i][pbn]);
210 	    printf("\n");
211 	}
212 
213 	t0 = tpb[i][3];
214 	if (!(t0 & 0xf0))
215 	    break;
216     }
217 
218     if (nhb) {
219 	hb = ap;
220 	ap += nhb;
221 	if (flags & STRV) {
222 	    printf("%d historical bytes:", nhb);
223 	    for (i = 0; i < nhb; i++) {
224 		c = hb[i];
225 		if (c >= ' ' && c <= '~')
226 		    printf(" %c", c);
227 		else
228 		    printf(" %02x", c);
229 	    }
230 	    printf("\n");
231 	}
232     }
233 
234     if (hiproto > 0)
235 	ap++;
236 
237     if (ap - atr < len && (flags & STRLEN))
238 	len = ap - atr;
239 
240     if (hiproto > 0) {
241 	tck = 0;
242 	for (i = 1; i < len; i++)
243 	    tck ^= atr[i];
244 	if (tck != 0 && (flags & STRV))
245 	    printf("Checksum failed, TCK=%x sum=%x\n", atr[len-1], tck);
246     }
247 
248     /* got enough bytes? */
249 
250     if (ap - atr != len && (flags & STRV))
251 	printf("expected %d proto bytes + %d historical bytes, got %d\n", (int) (ap - atr) - nhb, nhb, len);
252     if (ap - atr > len) {
253 	if (flags & STRV)
254 	    printf("atr underrun\n");
255 	param->t = -1;
256 	return len;
257     }
258 
259     /*
260      * I'm a little unclear on this.  If TA2 is present, it indicates a specific mode.
261      * Else it's negotiable, and starts out with proto 1?
262      * 7816-3 6.6.1
263      */
264     if (TA2 != 0xff)
265 	t = TA2 & 0xf;
266     else
267 	t = TD1 & 0xf;
268 
269     for (i = 0; bps[i].bps; i++) {
270 	if (((TA1 >> 4) & 0xf) >= bps[i].Fi && (TA1 & 0xf) >= bps[i].Di) {
271 	    if (flags & STRV)
272 		printf("speed %ld\n", (long) bps[i].bps);
273 	    Fi = bps[i].Fi;
274 	    Di = bps[i].Di;
275 	    break;
276 	}
277     }
278 
279     F  = Ftab[Fi];
280     D  = Dtab[Di];
281     N  = TC1;
282 
283     /* 1/f = 1/3.579545 ~= 50/179; etu in microsec */
284     param->etu = etu = (F * 50L) / (D * 179L);
285     param->n = (N < 255) ? N : 0;
286 
287     if (flags & STRV) {
288 	printf("%d etu = %d F / %d D * 3.58 f\n", etu, F, D);
289 	if (N)
290 	    printf("%d N\n", N);
291     }
292 
293     if (t == 0) {
294 	WI = TC2;
295 
296 	/* cwt is in milliseconds */
297 	param->cwt = (960L * WI * F) / 3580L;
298 	if ((flags & STRV) && WI != 10)
299 	    printf("%d cwt = (960 * %d WI * %d F) / 3.58 f / 1000\n",
300 		   param->cwt, WI, F);
301     } else if (t == 1) {
302 	/* add 100 to each for engineering safety margin */
303 	param->cwt = (11L + (1 << (TB1 & 0xf))) * etu / 1000 + 100;
304 	param->bwt = (11L * etu / 1000L) + ((1 << ((TB1 >> 4) & 0xf)) * 100) + 100;
305 	if (flags & STRV)
306 	    printf("%d cwt, %d bwt\n", param->cwt, param->bwt);
307     }
308     param->t = t;
309 
310     return len;
311 }
312