1 /*
2 parse.c: parse CCID structure
3 Copyright (C) 2003-2010 Ludovic Rousseau
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc., 51
17 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 # ifdef S_SPLINT_S
23 # include <sys/types.h>
24 # endif
25 #include <errno.h>
26 #include <unistd.h>
27
28 #include "defs.h"
29 #include "ccid.h"
30
31 /* define DISPLAY_EXTRA_VALUES to display the extra (invalid) values
32 * returned by bNumClockSupported and bNumDataRatesSupported */
33 #undef DISPLAY_EXTRA_VALUES
34
35 #ifndef TRUE
36 #define TRUE 1
37 #define FALSE 0
38 #endif
39
40 #define BLUE "\33[34m"
41 #define RED "\33[31m"
42 #define BRIGHT_RED "\33[01;31m"
43 #define GREEN "\33[32m"
44 #define MAGENTA "\33[35m"
45 #define NORMAL "\33[0m"
46
47 /* global variables used in ccid_usb.c but defined in ifdhandler.c */
48 int LogLevel = 1+2+4+8; /* full debug */
49 int DriverOptions = 0;
50
51 static int ccid_parse_interface_descriptor(libusb_device_handle *handle,
52 struct libusb_device_descriptor desc,
53 struct libusb_config_descriptor *config_desc,
54 int num,
55 const struct libusb_interface *usb_interface);
56
57
58 /*****************************************************************************
59 *
60 * main
61 *
62 ****************************************************************************/
main(int argc,char * argv[])63 int main(int argc, char *argv[])
64 {
65 libusb_device **devs, *dev;
66 int nb = 0, r, i;
67 unsigned char buffer[256];
68 char class_ff = FALSE;
69 ssize_t cnt;
70
71 if ((argc > 1) && (0 == strcmp(argv[1], "-p")))
72 class_ff = TRUE;
73
74 r = libusb_init(NULL);
75 if (r < 0)
76 {
77 (void)printf("libusb_init() failed: %s\n", libusb_error_name(r));
78 return r;
79 }
80
81 cnt = libusb_get_device_list(NULL, &devs);
82 if (cnt < 0)
83 {
84 (void)printf("libusb_get_device_list() failed: %s\n",
85 libusb_error_name(r));
86 return (int)cnt;
87 }
88
89 /* for every device */
90 i = 0;
91 while ((dev = devs[i++]) != NULL)
92 {
93 struct libusb_device_descriptor desc;
94 struct libusb_config_descriptor *config_desc;
95 struct libusb_device_handle *handle;
96 const struct libusb_interface *usb_interface = NULL;
97 #ifndef __APPLE__
98 int interface;
99 #endif
100 int num = 0;
101
102 r = libusb_open(dev, &handle);
103 if (r < 0)
104 {
105 (void)fprintf(stderr, "Can't libusb_open(): %s\n",
106 libusb_error_name(r));
107 if (getuid())
108 {
109 (void)fprintf(stderr,
110 BRIGHT_RED "Please, restart the command as root\n" NORMAL);
111 return 1;
112 }
113 continue;
114 }
115
116 r = libusb_get_device_descriptor(dev, &desc);
117 if (r < 0)
118 {
119 (void)fprintf(stderr,
120 BRIGHT_RED "failed to get device descriptor: %s" NORMAL,
121 libusb_error_name(r));
122 return 1;
123 }
124
125 (void)fprintf(stderr,
126 "Parsing USB bus/device: %04X:%04X (bus %d, device %d)\n",
127 desc.idVendor, desc.idProduct,
128 libusb_get_bus_number(dev), libusb_get_device_address(dev));
129
130 (void)fprintf(stderr, " idVendor: 0x%04X", desc.idVendor);
131 r = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer,
132 buffer, sizeof(buffer));
133 if (r < 0)
134 {
135 (void)fprintf(stderr, " Can't get iManufacturer string: %s\n",
136 libusb_error_name(r));
137 if (getuid())
138 {
139 (void)fprintf(stderr,
140 BRIGHT_RED "Please, restart the command as root\n" NORMAL);
141 return 1;
142 }
143 }
144 else
145 (void)fprintf(stderr,
146 " iManufacturer: " BLUE "%s\n" NORMAL, buffer);
147
148 (void)fprintf(stderr, " idProduct: 0x%04X", desc.idProduct);
149 r = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
150 buffer, sizeof(buffer));
151 if (r < 0)
152 (void)fprintf(stderr, " Can't get iProduct string: %s\n",
153 libusb_error_name(r));
154 else
155 (void)fprintf(stderr, " iProduct: " BLUE "%s\n" NORMAL, buffer);
156
157 again:
158 /* check if the device has bInterfaceClass == 11 */
159 r = libusb_get_active_config_descriptor(dev, &config_desc);
160 if (r < 0)
161 {
162 (void)fprintf(stderr, " Can't get config descriptor: %s\n",
163 libusb_error_name(r));
164 (void)libusb_close(handle);
165 continue;
166 }
167
168 usb_interface = get_ccid_usb_interface(config_desc, &num);
169 if (NULL == usb_interface)
170 {
171 (void)libusb_close(handle);
172 /* only if we found no CCID interface */
173 if (0 == num)
174 (void)fprintf(stderr, RED " NOT a CCID/ICCD device\n" NORMAL);
175 continue;
176 }
177 if (!class_ff && (0xFF == usb_interface->altsetting->bInterfaceClass))
178 {
179 (void)libusb_close(handle);
180 (void)fprintf(stderr, MAGENTA " Found a possibly CCID/ICCD device (bInterfaceClass = 0xFF). Use %s -p\n" NORMAL, argv[0]);
181 continue;
182 }
183 (void)fprintf(stderr,
184 GREEN " Found a CCID/ICCD device at interface %d\n" NORMAL, num);
185
186 /* now we found a free reader and we try to use it */
187 #if 0
188 if (NULL == dev->config)
189 {
190 (void)libusb_close(handle);
191 (void)fprintf(stderr, "No dev->config found for %s/%s\n",
192 bus->dirname, dev->filename);
193 continue;
194 }
195 #endif
196
197 #ifndef __APPLE__
198 interface = usb_interface->altsetting->bInterfaceNumber;
199 r = libusb_claim_interface(handle, interface);
200 if (r < 0)
201 {
202 (void)fprintf(stderr,
203 "Can't claim interface (bus %d, device %d): %s\n",
204 libusb_get_bus_number(dev), libusb_get_device_address(dev),
205 libusb_error_name(r));
206 (void)libusb_close(handle);
207
208 if (EBUSY == errno)
209 {
210 (void)fprintf(stderr,
211 BRIGHT_RED " Please, stop pcscd and retry\n\n" NORMAL);
212
213 if (class_ff)
214 /* maybe the device with Class = 0xFF is NOT a CCID
215 * reader */
216 continue;
217 else
218 return TRUE;
219 }
220 continue;
221 }
222 #endif
223
224 (void)ccid_parse_interface_descriptor(handle, desc, config_desc, num,
225 usb_interface);
226 nb++;
227
228 #ifndef __APPLE__
229 (void)libusb_release_interface(handle, interface);
230 #endif
231 /* check for another CCID interface on the same device */
232 num++;
233 goto again;
234 }
235
236 if ((0 == nb) && (0 != geteuid()))
237 (void)fprintf(stderr,
238 "Can't find any CCID device.\nMaybe you must run parse as root?\n");
239
240 libusb_exit(NULL);
241
242 return 0;
243 } /* main */
244
245
246 /*****************************************************************************
247 *
248 * Parse a CCID USB Descriptor
249 *
250 ****************************************************************************/
ccid_parse_interface_descriptor(libusb_device_handle * handle,struct libusb_device_descriptor desc,struct libusb_config_descriptor * config_desc,int num,const struct libusb_interface * usb_interface)251 static int ccid_parse_interface_descriptor(libusb_device_handle *handle,
252 struct libusb_device_descriptor desc,
253 struct libusb_config_descriptor *config_desc,
254 int num,
255 const struct libusb_interface *usb_interface)
256 {
257 const struct libusb_interface_descriptor *usb_interface_descriptor;
258 const unsigned char *device_descriptor;
259 unsigned char buffer[256*sizeof(int)]; /* maximum is 256 records */
260 int r;
261
262 /*
263 * Vendor/model name
264 */
265 (void)printf(" idVendor: 0x%04X\n", desc.idVendor);
266 r = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer,
267 buffer, sizeof(buffer));
268 if (r < 0)
269 {
270 (void)printf(" Can't get iManufacturer string: %s\n",
271 libusb_error_name(r));
272 if (getuid())
273 {
274 (void)fprintf(stderr,
275 BRIGHT_RED "Please, restart the command as root\n\n" NORMAL);
276 return TRUE;
277 }
278 }
279 else
280 (void)printf(" iManufacturer: %s\n", buffer);
281
282 (void)printf(" idProduct: 0x%04X\n", desc.idProduct);
283 r = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
284 buffer, sizeof(buffer));
285 if (r < 0)
286 (void)printf(" Can't get iProduct string: %s\n",
287 libusb_error_name(r));
288 else
289 (void)printf(" iProduct: %s\n", buffer);
290
291 (void)printf(" bcdDevice: %X.%02X (firmware release?)\n",
292 desc.bcdDevice >> 8, desc.bcdDevice & 0xFF);
293
294 usb_interface_descriptor = get_ccid_usb_interface(config_desc, &num)->altsetting;
295
296 (void)printf(" bLength: %d\n", usb_interface_descriptor->bLength);
297
298 (void)printf(" bDescriptorType: %d\n", usb_interface_descriptor->bDescriptorType);
299
300 (void)printf(" bInterfaceNumber: %d\n", usb_interface_descriptor->bInterfaceNumber);
301
302 (void)printf(" bAlternateSetting: %d\n", usb_interface_descriptor->bAlternateSetting);
303
304 (void)printf(" bNumEndpoints: %d\n", usb_interface_descriptor->bNumEndpoints);
305 switch (usb_interface_descriptor->bNumEndpoints)
306 {
307 case 0:
308 (void)printf(" Control only\n");
309 break;
310 case 1:
311 (void)printf(" Interrupt-IN\n");
312 break;
313 case 2:
314 (void)printf(" bulk-IN and bulk-OUT\n");
315 break;
316 case 3:
317 (void)printf(" bulk-IN, bulk-OUT and Interrupt-IN\n");
318 break;
319 default:
320 (void)printf(" UNKNOWN value\n");
321 }
322
323 (void)printf(" bInterfaceClass: 0x%02X", usb_interface_descriptor->bInterfaceClass);
324 if (usb_interface_descriptor->bInterfaceClass == 0x0b)
325 (void)printf(" [Chip Card Interface Device Class (CCID)]\n");
326 else
327 {
328 (void)printf("\n NOT A CCID DEVICE\n");
329 if (usb_interface_descriptor->bInterfaceClass != 0xFF)
330 return TRUE;
331 else
332 (void)printf(" Class is 0xFF (proprietary)\n");
333 }
334
335 (void)printf(" bInterfaceSubClass: %d\n",
336 usb_interface_descriptor->bInterfaceSubClass);
337 if (usb_interface_descriptor->bInterfaceSubClass)
338 (void)printf(" UNSUPPORTED SubClass\n");
339
340 (void)printf(" bInterfaceProtocol: %d\n",
341 usb_interface_descriptor->bInterfaceProtocol);
342 switch (usb_interface_descriptor->bInterfaceProtocol)
343 {
344 case 0:
345 (void)printf(" bulk transfer, optional interrupt-IN (CCID)\n");
346 break;
347 case 1:
348 (void)printf(" ICCD Version A, Control transfers, (no interrupt-IN)\n");
349 break;
350 case 2:
351 (void)printf(" ICCD Version B, Control transfers, (optional interrupt-IN)\n");
352 break;
353 default:
354 (void)printf(" UNSUPPORTED InterfaceProtocol\n");
355 }
356
357 r = libusb_get_string_descriptor_ascii(handle, usb_interface_descriptor->iInterface,
358 buffer, sizeof(buffer));
359 if (r < 0)
360 (void)printf(" Can't get iInterface string: %s\n",
361 libusb_error_name(r));
362 else
363 (void)printf(" iInterface: %s\n", buffer);
364
365 device_descriptor = get_ccid_device_descriptor(usb_interface);
366 if (NULL == device_descriptor)
367 {
368 (void)printf("\n NOT A CCID DEVICE\n");
369 return TRUE;
370 }
371
372 /*
373 * CCID Class Descriptor
374 */
375 (void)printf(" CCID Class Descriptor\n");
376
377 (void)printf(" bLength: 0x%02X\n", device_descriptor[0]);
378 if (device_descriptor[0] != 0x36)
379 {
380 (void)printf(" UNSUPPORTED bLength\n");
381 return TRUE;
382 }
383
384 (void)printf(" bDescriptorType: 0x%02X\n", device_descriptor[1]);
385 if (device_descriptor[1] != 0x21)
386 {
387 if (0xFF == device_descriptor[1])
388 (void)printf(" PROPRIETARY bDescriptorType\n");
389 else
390 {
391 (void)printf(" UNSUPPORTED bDescriptorType\n");
392 return TRUE;
393 }
394 }
395
396 (void)printf(" bcdCCID: %X.%02X\n", device_descriptor[3], device_descriptor[2]);
397 (void)printf(" bMaxSlotIndex: 0x%02X\n", device_descriptor[4]);
398 (void)printf(" bVoltageSupport: 0x%02X\n", device_descriptor[5]);
399 if (device_descriptor[5] & 0x01)
400 (void)printf(" 5.0V\n");
401 if (device_descriptor[5] & 0x02)
402 (void)printf(" 3.0V\n");
403 if (device_descriptor[5] & 0x04)
404 (void)printf(" 1.8V\n");
405
406 (void)printf(" dwProtocols: 0x%02X%02X 0x%02X%02X\n", device_descriptor[9], device_descriptor[8],
407 device_descriptor[7], device_descriptor[6]);
408 if (device_descriptor[6] & 0x01)
409 (void)printf(" T=0\n");
410 if (device_descriptor[6] & 0x02)
411 (void)printf(" T=1\n");
412
413 (void)printf(" dwDefaultClock: %.3f MHz\n", dw2i(device_descriptor, 10)/1000.0);
414 (void)printf(" dwMaximumClock: %.3f MHz\n", dw2i(device_descriptor, 14)/1000.0);
415 int bNumClockSupported = device_descriptor[18];
416 (void)printf(" bNumClockSupported: %d%s\n", bNumClockSupported,
417 bNumClockSupported ? "" : " (will use whatever is returned)");
418 {
419 int n;
420
421 if (0 == bNumClockSupported)
422 /* read up to the buffer size */
423 bNumClockSupported = sizeof(buffer) / sizeof(int);
424
425 /* See CCID 5.3.2 page 24 */
426 n = libusb_control_transfer(handle,
427 0xA1, /* request type */
428 0x02, /* GET CLOCK FREQUENCIES */
429 0x00, /* value */
430 usb_interface_descriptor->bInterfaceNumber, /* interface */
431 buffer,
432 bNumClockSupported * sizeof(int),
433 2 * 1000);
434
435 /* we got an error? */
436 if (n <= 0)
437 {
438 (void)(void)printf(" IFD does not support GET CLOCK FREQUENCIES request: %s\n", libusb_error_name(n));
439 if (EBUSY == errno)
440 {
441 (void)fprintf(stderr,
442 BRIGHT_RED " Please, stop pcscd and retry\n\n" NORMAL);
443 return TRUE;
444 }
445 }
446 else
447 if (n % 4) /* not a multiple of 4 */
448 (void)printf(" wrong size for GET CLOCK FREQUENCIES: %d\n", n);
449 else
450 {
451 int i;
452
453 /* we do not get the expected number of data rates */
454 if ((n != bNumClockSupported*4) && bNumClockSupported)
455 {
456 (void)printf(" Got %d clock frequencies but was expecting %d\n",
457 n/4, bNumClockSupported);
458
459 /* we got more data than expected */
460 #ifndef DISPLAY_EXTRA_VALUES
461 if (n > bNumClockSupported*4)
462 n = bNumClockSupported*4;
463 #endif
464 }
465
466 for (i=0; i<n; i+=4)
467 (void)printf(" Support %d kHz\n", dw2i(buffer, i));
468 }
469 }
470 (void)printf(" dwDataRate: %d bps\n", dw2i(device_descriptor, 19));
471 (void)printf(" dwMaxDataRate: %d bps\n", dw2i(device_descriptor, 23));
472 int bNumDataRatesSupported = device_descriptor[27];
473 (void)printf(" bNumDataRatesSupported: %d%s\n", bNumDataRatesSupported,
474 bNumDataRatesSupported ? "" : " (will use whatever is returned)");
475 {
476 int n;
477 int n_max;
478
479 if (0 == bNumDataRatesSupported)
480 /* read up to the buffer size */
481 n_max = sizeof(buffer) / sizeof(int);
482 else
483 n_max = bNumDataRatesSupported;
484
485 /* See CCID 5.3.3 page 24 */
486 n = libusb_control_transfer(handle,
487 0xA1, /* request type */
488 0x03, /* GET DATA RATES */
489 0x00, /* value */
490 usb_interface_descriptor->bInterfaceNumber, /* interface */
491 buffer,
492 n_max * sizeof(int),
493 2 * 1000);
494
495 /* we got an error? */
496 if (n <= 0)
497 (void)printf(" IFD does not support GET_DATA_RATES request: %s\n",
498 libusb_error_name(n));
499 else
500 if (n % 4) /* not a multiple of 4 */
501 (void)printf(" wrong size for GET_DATA_RATES: %d\n", n);
502 else
503 {
504 int i;
505
506 /* we do not get the expected number of data rates */
507 if ((n != bNumDataRatesSupported*4) && bNumDataRatesSupported)
508 {
509 (void)printf(" Got %d data rates but was expecting %d\n", n/4,
510 bNumDataRatesSupported);
511
512 /* we got more data than expected */
513 #ifndef DISPLAY_EXTRA_VALUES
514 if (n > bNumDataRatesSupported*4)
515 n = bNumDataRatesSupported*4;
516 #endif
517 }
518
519 for (i=0; i<n; i+=4)
520 (void)printf(" Support %d bps\n", dw2i(buffer, i));
521 }
522 }
523 (void)printf(" dwMaxIFSD: %d\n", dw2i(device_descriptor, 28));
524 (void)printf(" dwSynchProtocols: 0x%08X\n", dw2i(device_descriptor, 32));
525 if (device_descriptor[32] & 0x01)
526 (void)printf(" 2-wire protocol\n");
527 if (device_descriptor[32] & 0x02)
528 (void)printf(" 3-wire protocol\n");
529 if (device_descriptor[32] & 0x04)
530 (void)printf(" I2C protocol\n");
531
532 (void)printf(" dwMechanical: 0x%08X\n", dw2i(device_descriptor, 36));
533 if (device_descriptor[36] == 0)
534 (void)printf(" No special characteristics\n");
535 if (device_descriptor[36] & 0x01)
536 (void)printf(" Card accept mechanism\n");
537 if (device_descriptor[36] & 0x02)
538 (void)printf(" Card ejection mechanism\n");
539 if (device_descriptor[36] & 0x04)
540 (void)printf(" Card capture mechanism\n");
541 if (device_descriptor[36] & 0x08)
542 (void)printf(" Card lock/unlock mechanism\n");
543
544 (void)printf(" dwFeatures: 0x%08X\n", dw2i(device_descriptor, 40));
545 if (dw2i(device_descriptor, 40) == 0)
546 (void)printf(" No special characteristics\n");
547 if (device_descriptor[40] & 0x02)
548 (void)printf(" ....02 Automatic parameter configuration based on ATR data\n");
549 if (device_descriptor[40] & 0x04)
550 (void)printf(" ....04 Automatic activation of ICC on inserting\n");
551 if (device_descriptor[40] & 0x08)
552 (void)printf(" ....08 Automatic ICC voltage selection\n");
553 if (device_descriptor[40] & 0x10)
554 (void)printf(" ....10 Automatic ICC clock frequency change according to parameters\n");
555 if (device_descriptor[40] & 0x20)
556 (void)printf(" ....20 Automatic baud rate change according to frequency and Fi, Di params\n");
557 if (device_descriptor[40] & 0x40)
558 (void)printf(" ....40 Automatic parameters negotiation made by the CCID\n");
559 if (device_descriptor[40] & 0x80)
560 (void)printf(" ....80 Automatic PPS made by the CCID\n");
561 if (device_descriptor[41] & 0x01)
562 (void)printf(" ..01.. CCID can set ICC in clock stop mode\n");
563 if (device_descriptor[41] & 0x02)
564 (void)printf(" ..02.. NAD value other than 00 accepted (T=1)\n");
565 if (device_descriptor[41] & 0x04)
566 (void)printf(" ..04.. Automatic IFSD exchange as first exchange (T=1)\n");
567 if (device_descriptor[41] & 0x08)
568 (void)printf(" ..08.. ICCD token\n");
569 switch (device_descriptor[42] & 0x07)
570 {
571 case 0x00:
572 (void)printf(" 00.... Character level exchange\n");
573 break;
574
575 case 0x01:
576 (void)printf(" 01.... TPDU level exchange\n");
577 break;
578
579 case 0x02:
580 (void)printf(" 02.... Short APDU level exchange\n");
581 break;
582
583 case 0x04:
584 (void)printf(" 04.... Short and Extended APDU level exchange\n");
585 break;
586 }
587 if (device_descriptor[42] & 0x10)
588 (void)printf(" 10.... USB Wake up signaling supported on card insertion and removal\n");
589
590 (void)printf(" dwMaxCCIDMessageLength: %d bytes\n", dw2i(device_descriptor, 44));
591 (void)printf(" bClassGetResponse: 0x%02X\n", device_descriptor[48]);
592 if (0xFF == device_descriptor[48])
593 (void)printf(" echoes the APDU class\n");
594 (void)printf(" bClassEnvelope: 0x%02X\n", device_descriptor[49]);
595 if (0xFF == device_descriptor[49])
596 (void)printf(" echoes the APDU class\n");
597 (void)printf(" wLcdLayout: 0x%04X\n", (device_descriptor[51] << 8)+device_descriptor[50]);
598 if (device_descriptor[51])
599 (void)printf(" %2d lines\n", device_descriptor[51]);
600 if (device_descriptor[50])
601 (void)printf(" %2d characters per line\n", device_descriptor[50]);
602 (void)printf(" bPINSupport: 0x%02X\n", device_descriptor[52]);
603 if (device_descriptor[52] & 0x01)
604 (void)printf(" PIN Verification supported\n");
605 if (device_descriptor[52] & 0x02)
606 (void)printf(" PIN Modification supported\n");
607 (void)printf(" bMaxCCIDBusySlots: %d\n", device_descriptor[53]);
608
609 return FALSE;
610 } /* ccid_parse_interface_descriptor */
611
612