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 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 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 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