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