1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2019, Joyent, Inc.
14 */
15
16 /*
17 * Verify that we can parse various forms of ATR data and detect invalid data.
18 */
19
20 #include <err.h>
21 #include <stdlib.h>
22
23 #include <atr.h>
24
25 typedef struct atr_vals {
26 } atr_vals_t;
27
28 typedef struct atr_test {
29 const char *ar_test;
30 uint8_t ar_len;
31 uint8_t ar_buf[64];
32 atr_parsecode_t ar_retval;
33 /* Everything after this is data from the ATR */
34 atr_protocol_t ar_sup;
35 atr_protocol_t ar_def;
36 boolean_t ar_neg;
37 uint8_t ar_fi;
38 uint8_t ar_di;
39 atr_convention_t ar_conv;
40 uint8_t ar_guard;
41 atr_clock_stop_t ar_stop;
42 /* These will be checked based on sup prot */
43 uint8_t ar_t0_wi;
44 atr_t1_checksum_t ar_t1_cksum;
45 uint8_t ar_t1_bwi;
46 uint8_t ar_t1_cwi;
47 uint8_t ar_t1_ifsc;
48 } atr_test_t;
49
50 atr_test_t atr_tests[] = {
51 { "zero-length data", 0, { 0 }, ATR_CODE_TOO_SHORT },
52 { "No T0", 1, { 0x3f }, ATR_CODE_TOO_SHORT },
53 { "Too much data", 34, { 0 }, ATR_CODE_TOO_LONG },
54 { "Overrun T0 (1)", 2, { 0x3b, 0x10 }, ATR_CODE_OVERRUN },
55 { "Overrun T0 (2)", 2, { 0x3b, 0x80 }, ATR_CODE_OVERRUN },
56 { "Overrun T0 (3)", 2, { 0x3b, 0x01 }, ATR_CODE_OVERRUN },
57 { "Overrun T0 (4)", 2, { 0x3b, 0x11 }, ATR_CODE_OVERRUN },
58 { "Overrun T0 (5)", 2, { 0x3b, 0xff }, ATR_CODE_OVERRUN },
59 { "Overrun TD1", 3, { 0x3b, 0x80, 0x10 }, ATR_CODE_OVERRUN },
60 { "Overrun TD2", 4, { 0x3b, 0x80, 0x80, 0x10 }, ATR_CODE_OVERRUN },
61 { "Overrun TD", 33, { 0x3b, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
62 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
63 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
64 0x80, 0x80, 0x80 }, ATR_CODE_OVERRUN },
65 { "T0 w/ T=15 and no cksum", 5, { 0x3b, 0x80, 0x80, 0x1f, 0x00 },
66 ATR_CODE_OVERRUN },
67 { "Bad TS (1)", 2, { 0x3a, 0x00 }, ATR_CODE_INVALID_TS },
68 { "Bad TS (2)", 2, { 0xff, 0x00 }, ATR_CODE_INVALID_TS },
69 { "T0 w/ T=15 and bad cksum", 6, { 0x3b, 0x80, 0x80, 0x1f, 0x00, 0x00 },
70 ATR_CODE_CHECKSUM_ERROR },
71 { "T0 w/ T=15 and bad cksum (make sure no TS)", 6,
72 { 0x3b, 0x80, 0x80, 0x1f, 0x00, 0x24 },
73 ATR_CODE_CHECKSUM_ERROR },
74 { "T=15 in TD1", 4, { 0x3b, 0x80, 0x0f, 0x8f }, ATR_CODE_INVALID_TD1 },
75 {
76 .ar_test = "Minimal T0 Direct",
77 .ar_len = 2,
78 .ar_buf = { 0x3b, 0x00 },
79 .ar_sup = ATR_P_T0,
80 .ar_def = ATR_P_T0,
81 .ar_neg = B_TRUE,
82 .ar_fi = 1,
83 .ar_di = 1,
84 .ar_conv = ATR_CONVENTION_DIRECT,
85 .ar_guard = 0,
86 .ar_stop = ATR_CLOCK_STOP_NONE,
87 .ar_t0_wi = 10,
88 }, {
89 .ar_test = "Minimal T0 Inverse",
90 .ar_len = 2,
91 .ar_buf = { 0x3f, 0x00 },
92 .ar_sup = ATR_P_T0,
93 .ar_def = ATR_P_T0,
94 .ar_neg = B_TRUE,
95 .ar_fi = 1,
96 .ar_di = 1,
97 .ar_conv = ATR_CONVENTION_INVERSE,
98 .ar_guard = 0,
99 .ar_stop = ATR_CLOCK_STOP_NONE,
100 .ar_t0_wi = 10,
101 }, {
102 .ar_test = "T0 Fi/Di (1)",
103 .ar_len = 3,
104 .ar_buf = { 0x3b, 0x10, 0x24 },
105 .ar_sup = ATR_P_T0,
106 .ar_def = ATR_P_T0,
107 .ar_neg = B_TRUE,
108 .ar_fi = 2,
109 .ar_di = 4,
110 .ar_conv = ATR_CONVENTION_DIRECT,
111 .ar_guard = 0,
112 .ar_stop = ATR_CLOCK_STOP_NONE,
113 .ar_t0_wi = 10,
114 }, {
115 .ar_test = "T0 Fi/Di (2)",
116 .ar_len = 3,
117 .ar_buf = { 0x3b, 0x10, 0x93 },
118 .ar_sup = ATR_P_T0,
119 .ar_def = ATR_P_T0,
120 .ar_neg = B_TRUE,
121 .ar_fi = 9,
122 .ar_di = 3,
123 .ar_conv = ATR_CONVENTION_DIRECT,
124 .ar_guard = 0,
125 .ar_stop = ATR_CLOCK_STOP_NONE,
126 .ar_t0_wi = 10,
127 }, {
128 .ar_test = "T0 Ignore deprecated TB1",
129 .ar_len = 3,
130 .ar_buf = { 0x3b, 0x20, 0x42 },
131 .ar_sup = ATR_P_T0,
132 .ar_def = ATR_P_T0,
133 .ar_neg = B_TRUE,
134 .ar_fi = 1,
135 .ar_di = 1,
136 .ar_conv = ATR_CONVENTION_DIRECT,
137 .ar_guard = 0,
138 .ar_stop = ATR_CLOCK_STOP_NONE,
139 .ar_t0_wi = 10,
140 }, {
141 .ar_test = "T0 Ignore deprecated TB2",
142 .ar_len = 4,
143 .ar_buf = { 0x3b, 0x80, 0x20, 0x42 },
144 .ar_sup = ATR_P_T0,
145 .ar_def = ATR_P_T0,
146 .ar_neg = B_TRUE,
147 .ar_fi = 1,
148 .ar_di = 1,
149 .ar_conv = ATR_CONVENTION_DIRECT,
150 .ar_guard = 0,
151 .ar_stop = ATR_CLOCK_STOP_NONE,
152 .ar_t0_wi = 10,
153 }, {
154 .ar_test = "T0 Ignore deprecated TB1/TB2",
155 .ar_len = 5,
156 .ar_buf = { 0x3b, 0xa0, 0x55, 0x20, 0x42 },
157 .ar_sup = ATR_P_T0,
158 .ar_def = ATR_P_T0,
159 .ar_neg = B_TRUE,
160 .ar_fi = 1,
161 .ar_di = 1,
162 .ar_conv = ATR_CONVENTION_DIRECT,
163 .ar_guard = 0,
164 .ar_stop = ATR_CLOCK_STOP_NONE,
165 .ar_t0_wi = 10,
166 }, {
167 .ar_test = "T0 Encode TC1",
168 .ar_len = 3,
169 .ar_buf = { 0x3b, 0x40, 0x23 },
170 .ar_sup = ATR_P_T0,
171 .ar_def = ATR_P_T0,
172 .ar_neg = B_TRUE,
173 .ar_fi = 1,
174 .ar_di = 1,
175 .ar_conv = ATR_CONVENTION_DIRECT,
176 .ar_guard = 0x23,
177 .ar_stop = ATR_CLOCK_STOP_NONE,
178 .ar_t0_wi = 10,
179 }, {
180 .ar_test = "T0 TA2 says neg",
181 .ar_len = 4,
182 .ar_buf = { 0x3b, 0x80, 0x10, 0x00 },
183 .ar_sup = ATR_P_T0,
184 .ar_def = ATR_P_T0,
185 .ar_neg = B_TRUE,
186 .ar_fi = 1,
187 .ar_di = 1,
188 .ar_conv = ATR_CONVENTION_DIRECT,
189 .ar_guard = 0,
190 .ar_stop = ATR_CLOCK_STOP_NONE,
191 .ar_t0_wi = 10,
192 }, {
193 .ar_test = "T0 TA2 says not neg",
194 .ar_len = 4,
195 .ar_buf = { 0x3b, 0x80, 0x10, 0x80 },
196 .ar_sup = ATR_P_T0,
197 .ar_def = ATR_P_T0,
198 .ar_neg = B_FALSE,
199 .ar_fi = 1,
200 .ar_di = 1,
201 .ar_conv = ATR_CONVENTION_DIRECT,
202 .ar_guard = 0,
203 .ar_stop = ATR_CLOCK_STOP_NONE,
204 .ar_t0_wi = 10,
205 }, {
206 .ar_test = "T0 TA2 says not neg, honor Fi/Di",
207 .ar_len = 5,
208 .ar_buf = { 0x3b, 0x90, 0x24, 0x10, 0x80 },
209 .ar_sup = ATR_P_T0,
210 .ar_def = ATR_P_T0,
211 .ar_neg = B_FALSE,
212 .ar_fi = 2,
213 .ar_di = 4,
214 .ar_conv = ATR_CONVENTION_DIRECT,
215 .ar_guard = 0,
216 .ar_stop = ATR_CLOCK_STOP_NONE,
217 .ar_t0_wi = 10,
218 }, {
219 .ar_test = "T0 TA2 says not neg, don't honor Fi/Di",
220 .ar_len = 5,
221 .ar_buf = { 0x3b, 0x90, 0x24, 0x10, 0x90 },
222 .ar_sup = ATR_P_T0,
223 .ar_def = ATR_P_T0,
224 .ar_neg = B_FALSE,
225 .ar_fi = 1,
226 .ar_di = 1,
227 .ar_conv = ATR_CONVENTION_DIRECT,
228 .ar_guard = 0,
229 .ar_stop = ATR_CLOCK_STOP_NONE,
230 .ar_t0_wi = 10,
231 }, {
232 .ar_test = "T0 TC2 set",
233 .ar_len = 4,
234 .ar_buf = { 0x3b, 0x80, 0x40, 0x35 },
235 .ar_sup = ATR_P_T0,
236 .ar_def = ATR_P_T0,
237 .ar_neg = B_TRUE,
238 .ar_fi = 1,
239 .ar_di = 1,
240 .ar_conv = ATR_CONVENTION_DIRECT,
241 .ar_guard = 0,
242 .ar_stop = ATR_CLOCK_STOP_NONE,
243 .ar_t0_wi = 0x35,
244 }, {
245 .ar_test = "T0 T15 empty (requires checksum)",
246 .ar_len = 5,
247 .ar_buf = { 0x3b, 0x80, 0x80, 0x0f, 0x0f },
248 .ar_sup = ATR_P_T0,
249 .ar_def = ATR_P_T0,
250 .ar_neg = B_TRUE,
251 .ar_fi = 1,
252 .ar_di = 1,
253 .ar_conv = ATR_CONVENTION_DIRECT,
254 .ar_guard = 0,
255 .ar_stop = ATR_CLOCK_STOP_NONE,
256 .ar_t0_wi = 10,
257 }, {
258 .ar_test = "T0 T15 Clock Stop (1)",
259 .ar_len = 6,
260 .ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x07, 0x18 },
261 .ar_sup = ATR_P_T0,
262 .ar_def = ATR_P_T0,
263 .ar_neg = B_TRUE,
264 .ar_fi = 1,
265 .ar_di = 1,
266 .ar_conv = ATR_CONVENTION_DIRECT,
267 .ar_guard = 0,
268 .ar_stop = ATR_CLOCK_STOP_NONE,
269 .ar_t0_wi = 10,
270 }, {
271 .ar_test = "T0 T15 Clock Stop (2)",
272 .ar_len = 6,
273 .ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x47, 0x58 },
274 .ar_sup = ATR_P_T0,
275 .ar_def = ATR_P_T0,
276 .ar_neg = B_TRUE,
277 .ar_fi = 1,
278 .ar_di = 1,
279 .ar_conv = ATR_CONVENTION_DIRECT,
280 .ar_guard = 0,
281 .ar_stop = ATR_CLOCK_STOP_LOW,
282 .ar_t0_wi = 10,
283 }, {
284 .ar_test = "T0 T15 Clock Stop (3)",
285 .ar_len = 6,
286 .ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0x87, 0x98 },
287 .ar_sup = ATR_P_T0,
288 .ar_def = ATR_P_T0,
289 .ar_neg = B_TRUE,
290 .ar_fi = 1,
291 .ar_di = 1,
292 .ar_conv = ATR_CONVENTION_DIRECT,
293 .ar_guard = 0,
294 .ar_stop = ATR_CLOCK_STOP_HI,
295 .ar_t0_wi = 10,
296 }, {
297 .ar_test = "T0 T15 Clock Stop (4)",
298 .ar_len = 6,
299 .ar_buf = { 0x3b, 0x80, 0x80, 0x1f, 0xc7, 0xd8 },
300 .ar_sup = ATR_P_T0,
301 .ar_def = ATR_P_T0,
302 .ar_neg = B_TRUE,
303 .ar_fi = 1,
304 .ar_di = 1,
305 .ar_conv = ATR_CONVENTION_DIRECT,
306 .ar_guard = 0,
307 .ar_stop = ATR_CLOCK_STOP_BOTH,
308 .ar_t0_wi = 10,
309 }, {
310 .ar_test = "T0 with random prots",
311 .ar_len = 7,
312 .ar_buf = { 0x3b, 0x80, 0x84, 0x85, 0x88, 0x0f, 0x06 },
313 .ar_sup = ATR_P_T0,
314 /*
315 * This comes from the fact that TD1 is T=4 and that isn't
316 * supported in the system.
317 */
318 .ar_def = ATR_P_NONE,
319 .ar_neg = B_TRUE,
320 .ar_fi = 1,
321 .ar_di = 1,
322 .ar_conv = ATR_CONVENTION_DIRECT,
323 .ar_guard = 0,
324 .ar_stop = ATR_CLOCK_STOP_NONE,
325 .ar_t0_wi = 10,
326 }, {
327 .ar_test = "Actual ATR (1, Yubikey4)",
328 .ar_len = 18,
329 .ar_buf = { 0x3b, 0xf8, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe,
330 0x15, 0x59, 0x75, 0x62, 0x69, 0x6b, 0x65, 0x79, 0x34,
331 0xd4 },
332 .ar_sup = ATR_P_T1,
333 .ar_def = ATR_P_T1,
334 .ar_neg = B_TRUE,
335 .ar_fi = 1,
336 .ar_di = 3,
337 .ar_conv = ATR_CONVENTION_DIRECT,
338 .ar_guard = 0,
339 .ar_stop = ATR_CLOCK_STOP_NONE,
340 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
341 .ar_t1_bwi = 1,
342 .ar_t1_cwi = 5,
343 .ar_t1_ifsc = 254
344 }, {
345 .ar_test = "Actual ATR (2)",
346 .ar_len = 19,
347 .ar_buf = { 0x3b, 0xf9, 0x18, 0x00, 0x00, 0x81, 0x31, 0xfe,
348 0x45, 0x4a, 0x32, 0x44, 0x30, 0x38, 0x31, 0x5f, 0x50, 0x56,
349 0xb6 },
350 .ar_sup = ATR_P_T1,
351 .ar_def = ATR_P_T1,
352 .ar_neg = B_TRUE,
353 .ar_fi = 1,
354 .ar_di = 8,
355 .ar_conv = ATR_CONVENTION_DIRECT,
356 .ar_guard = 0,
357 .ar_stop = ATR_CLOCK_STOP_NONE,
358 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
359 .ar_t1_bwi = 4,
360 .ar_t1_cwi = 5,
361 .ar_t1_ifsc = 254
362 }, {
363 .ar_test = "Actual ATR (3)",
364 .ar_len = 22,
365 .ar_buf = { 0x3b, 0xfc, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80,
366 0x45, 0x90, 0x67, 0x46, 0x4a, 0x00, 0x64, 0x16, 0x6, 0xf2,
367 0x72, 0x7e, 0x00, 0xe0 },
368 .ar_sup = ATR_P_T1,
369 .ar_def = ATR_P_T1,
370 .ar_neg = B_TRUE,
371 .ar_fi = 1,
372 .ar_di = 8,
373 .ar_conv = ATR_CONVENTION_DIRECT,
374 .ar_guard = 0,
375 .ar_stop = ATR_CLOCK_STOP_NONE,
376 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
377 .ar_t1_bwi = 4,
378 .ar_t1_cwi = 5,
379 .ar_t1_ifsc = 128
380 }, {
381 .ar_test = "Minimal T=1",
382 .ar_len = 4,
383 .ar_buf = { 0x3b, 0x80, 0x01, 0x81 },
384 .ar_sup = ATR_P_T1,
385 .ar_def = ATR_P_T1,
386 .ar_neg = B_TRUE,
387 .ar_fi = 1,
388 .ar_di = 1,
389 .ar_conv = ATR_CONVENTION_DIRECT,
390 .ar_guard = 0,
391 .ar_stop = ATR_CLOCK_STOP_NONE,
392 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
393 .ar_t1_bwi = 4,
394 .ar_t1_cwi = 13,
395 .ar_t1_ifsc = 32
396 }, {
397 .ar_test = "T=1 Fi/Di",
398 .ar_len = 5,
399 .ar_buf = { 0x3b, 0x90, 0x34, 0x01, 0xa5 },
400 .ar_sup = ATR_P_T1,
401 .ar_def = ATR_P_T1,
402 .ar_neg = B_TRUE,
403 .ar_fi = 3,
404 .ar_di = 4,
405 .ar_conv = ATR_CONVENTION_DIRECT,
406 .ar_guard = 0,
407 .ar_stop = ATR_CLOCK_STOP_NONE,
408 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
409 .ar_t1_bwi = 4,
410 .ar_t1_cwi = 13,
411 .ar_t1_ifsc = 32
412 }, {
413 .ar_test = "T=1 TA2 says neg, T=1 def",
414 .ar_len = 5,
415 .ar_buf = { 0x3b, 0x80, 0x11, 0x11, 0x80 },
416 .ar_sup = ATR_P_T1,
417 .ar_def = ATR_P_T1,
418 .ar_neg = B_TRUE,
419 .ar_fi = 1,
420 .ar_di = 1,
421 .ar_conv = ATR_CONVENTION_DIRECT,
422 .ar_guard = 0,
423 .ar_stop = ATR_CLOCK_STOP_NONE,
424 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
425 .ar_t1_bwi = 4,
426 .ar_t1_cwi = 13,
427 .ar_t1_ifsc = 32
428 }, {
429 .ar_test = "T=0, T=1 TA2 says neg, T=0 def",
430 .ar_len = 6,
431 .ar_buf = { 0x3b, 0x80, 0x90, 0x10, 0x01, 0x01 },
432 .ar_sup = ATR_P_T0 | ATR_P_T1,
433 .ar_def = ATR_P_T0,
434 .ar_neg = B_TRUE,
435 .ar_fi = 1,
436 .ar_di = 1,
437 .ar_conv = ATR_CONVENTION_DIRECT,
438 .ar_guard = 0,
439 .ar_stop = ATR_CLOCK_STOP_NONE,
440 .ar_t0_wi = 10,
441 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
442 .ar_t1_bwi = 4,
443 .ar_t1_cwi = 13,
444 .ar_t1_ifsc = 32
445 }, {
446 .ar_test = "T=0, T=1 TA2 says neg, T=1 def",
447 .ar_len = 6,
448 .ar_buf = { 0x3b, 0x80, 0x90, 0x11, 0x01, 0x00 },
449 .ar_sup = ATR_P_T0 | ATR_P_T1,
450 .ar_def = ATR_P_T1,
451 .ar_neg = B_TRUE,
452 .ar_fi = 1,
453 .ar_di = 1,
454 .ar_conv = ATR_CONVENTION_DIRECT,
455 .ar_guard = 0,
456 .ar_stop = ATR_CLOCK_STOP_NONE,
457 .ar_t0_wi = 10,
458 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
459 .ar_t1_bwi = 4,
460 .ar_t1_cwi = 13,
461 .ar_t1_ifsc = 32
462 }, {
463 .ar_test = "T=0, T=1 TA2 says not neg, T=0 def",
464 .ar_len = 6,
465 .ar_buf = { 0x3b, 0x80, 0x90, 0x90, 0x01, 0x81 },
466 .ar_sup = ATR_P_T0 | ATR_P_T1,
467 .ar_def = ATR_P_T0,
468 .ar_neg = B_FALSE,
469 .ar_fi = 1,
470 .ar_di = 1,
471 .ar_conv = ATR_CONVENTION_DIRECT,
472 .ar_guard = 0,
473 .ar_stop = ATR_CLOCK_STOP_NONE,
474 .ar_t0_wi = 10,
475 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
476 .ar_t1_bwi = 4,
477 .ar_t1_cwi = 13,
478 .ar_t1_ifsc = 32
479 }, {
480 .ar_test = "T=0, T=1 TA2 says not neg, T=1 def",
481 .ar_len = 6,
482 .ar_buf = { 0x3b, 0x80, 0x90, 0x81, 0x01, 0x90 },
483 .ar_sup = ATR_P_T0 | ATR_P_T1,
484 .ar_def = ATR_P_T1,
485 .ar_neg = B_FALSE,
486 .ar_fi = 1,
487 .ar_di = 1,
488 .ar_conv = ATR_CONVENTION_DIRECT,
489 .ar_guard = 0,
490 .ar_stop = ATR_CLOCK_STOP_NONE,
491 .ar_t0_wi = 10,
492 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
493 .ar_t1_bwi = 4,
494 .ar_t1_cwi = 13,
495 .ar_t1_ifsc = 32
496 }, {
497 .ar_test = "T=1, BWI/CWI",
498 .ar_len = 6,
499 .ar_buf = { 0x3b, 0x80, 0x81, 0x21, 0x59, 0x79 },
500 .ar_sup = ATR_P_T1,
501 .ar_def = ATR_P_T1,
502 .ar_neg = B_TRUE,
503 .ar_fi = 1,
504 .ar_di = 1,
505 .ar_conv = ATR_CONVENTION_DIRECT,
506 .ar_guard = 0,
507 .ar_stop = ATR_CLOCK_STOP_NONE,
508 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
509 .ar_t1_bwi = 5,
510 .ar_t1_cwi = 9,
511 .ar_t1_ifsc = 32
512 }, {
513 .ar_test = "T=1, IFSC",
514 .ar_len = 6,
515 .ar_buf = { 0x3b, 0x80, 0x81, 0x11, 0x49, 0x59 },
516 .ar_sup = ATR_P_T1,
517 .ar_def = ATR_P_T1,
518 .ar_neg = B_TRUE,
519 .ar_fi = 1,
520 .ar_di = 1,
521 .ar_conv = ATR_CONVENTION_DIRECT,
522 .ar_guard = 0,
523 .ar_stop = ATR_CLOCK_STOP_NONE,
524 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
525 .ar_t1_bwi = 4,
526 .ar_t1_cwi = 13,
527 .ar_t1_ifsc = 73
528 }, {
529 .ar_test = "T=1, Checksum (LRC)",
530 .ar_len = 6,
531 .ar_buf = { 0x3b, 0x80, 0x81, 0x41, 0x00, 0x40 },
532 .ar_sup = ATR_P_T1,
533 .ar_def = ATR_P_T1,
534 .ar_neg = B_TRUE,
535 .ar_fi = 1,
536 .ar_di = 1,
537 .ar_conv = ATR_CONVENTION_DIRECT,
538 .ar_guard = 0,
539 .ar_stop = ATR_CLOCK_STOP_NONE,
540 .ar_t1_cksum = ATR_T1_CHECKSUM_LRC,
541 .ar_t1_bwi = 4,
542 .ar_t1_cwi = 13,
543 .ar_t1_ifsc = 32
544 }, {
545 .ar_test = "T=1, Checksum (CRC)",
546 .ar_len = 6,
547 .ar_buf = { 0x3b, 0x80, 0x81, 0x41, 0x01, 0x41 },
548 .ar_sup = ATR_P_T1,
549 .ar_def = ATR_P_T1,
550 .ar_neg = B_TRUE,
551 .ar_fi = 1,
552 .ar_di = 1,
553 .ar_conv = ATR_CONVENTION_DIRECT,
554 .ar_guard = 0,
555 .ar_stop = ATR_CLOCK_STOP_NONE,
556 .ar_t1_cksum = ATR_T1_CHECKSUM_CRC,
557 .ar_t1_bwi = 4,
558 .ar_t1_cwi = 13,
559 .ar_t1_ifsc = 32
560 }
561 };
562
563 static void
atr_parse_failed(atr_test_t * test,const char * fmt,...)564 atr_parse_failed(atr_test_t *test, const char *fmt, ...)
565 {
566 va_list ap;
567
568 va_start(ap, fmt);
569 (void) fprintf(stderr, "Test \"%s\" failed: ", test->ar_test);
570 (void) vfprintf(stderr, fmt, ap);
571 (void) fprintf(stderr, "\n");
572 va_end(ap);
573 }
574
575 static uint_t
atr_parse_one(atr_data_t * data,atr_test_t * test)576 atr_parse_one(atr_data_t *data, atr_test_t *test)
577 {
578 uint_t err = 0;
579 atr_parsecode_t ret;
580 atr_protocol_t sup, def;
581 boolean_t neg;
582 uint8_t fi, di, guard;
583 atr_convention_t conv;
584 atr_clock_stop_t stop;
585
586 ret = atr_parse(test->ar_buf, test->ar_len, data);
587 if (ret != test->ar_retval) {
588 atr_parse_failed(test, "found unexpected return "
589 "value: %u (%s), expected: %u", ret, atr_strerror(ret),
590 test->ar_retval);
591 return (1);
592 }
593
594 /* Don't test anything else if it's not OK */
595 if (ret != ATR_CODE_OK)
596 return (0);
597
598 sup = atr_supported_protocols(data);
599 def = atr_default_protocol(data);
600 neg = atr_params_negotiable(data);
601 fi = atr_fi_index(data);
602 di = atr_di_index(data);
603 conv = atr_convention(data);
604 guard = atr_extra_guardtime(data);
605 stop = atr_clock_stop(data);
606
607 if (sup != test->ar_sup) {
608 atr_parse_failed(test, "Found mismatched supported "
609 "protocols: %u, expected: %u", sup, test->ar_sup);
610 err++;
611 }
612
613 if (def != test->ar_def) {
614 atr_parse_failed(test, "Found mismatched default "
615 "protocols: %u, expected: %u", def, test->ar_def);
616 err++;
617 }
618
619 if (neg != test->ar_neg) {
620 atr_parse_failed(test, "Found mismatched negotiable bit: "
621 "%u, expected %u", neg, test->ar_neg);
622 err++;
623 }
624
625 if (fi != test->ar_fi) {
626 atr_parse_failed(test, "Found mismatched fi index: "
627 "%u, expected: %u", fi, test->ar_fi);
628 err++;
629 }
630
631 if (di != test->ar_di) {
632 atr_parse_failed(test, "Found mismatched di index: "
633 "%u, expected: %u", di, test->ar_di);
634 err++;
635 }
636
637 if (conv != test->ar_conv) {
638 atr_parse_failed(test, "Found mismatched TS convention: "
639 "%u, expected: %u", conv, test->ar_conv);
640 err++;
641 }
642
643 if (guard != test->ar_guard) {
644 atr_parse_failed(test, "Found mismatched extra guardtime: "
645 "%u, expected: %u", guard, test->ar_guard);
646 err++;
647 }
648
649 if (stop != test->ar_stop) {
650 atr_parse_failed(test, "Found mismatched clock stop: "
651 "%u, expected: %u", stop, test->ar_stop);
652 err++;
653 }
654
655 if ((sup & ATR_P_T0) != 0) {
656 uint8_t wi;
657
658 wi = atr_t0_wi(data);
659 if (wi != test->ar_t0_wi) {
660 atr_parse_failed(test, "Found mismatched T0 wi: "
661 "%u, expected: %u", wi, test->ar_t0_wi);
662 err++;
663 }
664 }
665
666 if ((sup & ATR_P_T1) != 0) {
667 atr_t1_checksum_t cksum;
668 uint8_t bwi, cwi, ifsc;
669
670 cksum = atr_t1_checksum(data);
671 bwi = atr_t1_bwi(data);
672 cwi = atr_t1_cwi(data);
673 ifsc = atr_t1_ifsc(data);
674
675 if (cksum != test->ar_t1_cksum) {
676 atr_parse_failed(test, "Found mistmatched T1 checksum: "
677 "%u, expected: %u", cksum, test->ar_t1_cksum);
678 err++;
679 }
680
681 if (bwi != test->ar_t1_bwi) {
682 atr_parse_failed(test, "Found mistmatched T1 bwi: "
683 "%u, expected: %u", bwi, test->ar_t1_bwi);
684 err++;
685 }
686
687 if (cwi != test->ar_t1_cwi) {
688 atr_parse_failed(test, "Found mistmatched T1 cwi: "
689 "%u, expected: %u", cwi, test->ar_t1_cwi);
690 err++;
691 }
692
693 if (ifsc != test->ar_t1_ifsc) {
694 atr_parse_failed(test, "Found mistmatched T1 ifsc: "
695 "%u, expected: %u", ifsc, test->ar_t1_ifsc);
696 err++;
697 }
698 }
699
700 if (err > 0) {
701 atr_data_dump(data, stderr);
702 return (1);
703 }
704
705 return (0);
706 }
707
708 int
main(void)709 main(void)
710 {
711 uint_t i;
712 uint_t errs = 0;
713 atr_data_t *data;
714
715 data = atr_data_alloc();
716 if (data == NULL) {
717 errx(EXIT_FAILURE, "failed to allocate atr_data_t");
718 }
719
720 for (i = 0; i < sizeof (atr_tests) / sizeof (atr_test_t); i++) {
721 atr_data_reset(data);
722 errs += atr_parse_one(data, &atr_tests[i]);
723 }
724
725 atr_data_free(data);
726
727 if (errs != 0) {
728 warnx("%d test(s) failed", errs);
729 }
730 return (errs != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
731 }
732