/[pcsclite]/trunk/Drivers/ccid/src/ccid.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/ccid.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6274 - (show annotations) (download)
Fri Apr 13 13:45:16 2012 UTC (13 months, 1 week ago) by rousseau
File MIME type: text/plain
File size: 15755 byte(s)
Use %zd instead of %ld for size_t size

Fix compiler warning
ccid.c: In function `dump_gemalto_firmware_features':
ccid.c:122:2: warning: format `%ld' expects argument of type `long int',
but argument 6 has type `unsigned int' [-Wformat]

sizeof returns a size_t value with a variable length depending on the
architecture.
1 /*
2 ccid.c: CCID common code
3 Copyright (C) 2003-2010 Ludovic Rousseau
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this library; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21 * $Id$
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <pcsclite.h>
28 #include <ifdhandler.h>
29
30 #include "config.h"
31 #include "debug.h"
32 #include "ccid.h"
33 #include "defs.h"
34 #include "ccid_ifdhandler.h"
35 #include "commands.h"
36
37 #ifdef __APPLE__
38 #include <CoreFoundation/CoreFoundation.h>
39 #endif
40
41 /*****************************************************************************
42 *
43 * ccid_open_hack_pre
44 *
45 ****************************************************************************/
46 int ccid_open_hack_pre(unsigned int reader_index)
47 {
48 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
49
50 switch (ccid_descriptor->readerID)
51 {
52 case CARDMAN3121+1:
53 /* Reader announces APDU but is in fact TPDU */
54 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
55 ccid_descriptor->dwFeatures |= CCID_CLASS_TPDU;
56 break;
57
58 case MYSMARTPAD:
59 ccid_descriptor->dwMaxIFSD = 254;
60 break;
61
62 case CL1356D:
63 /* the firmware needs some time to initialize */
64 (void)sleep(1);
65 ccid_descriptor->readTimeout = 60*1000; /* 60 seconds */
66 break;
67 }
68
69 /* CCID */
70 if ((PROTOCOL_CCID == ccid_descriptor->bInterfaceProtocol)
71 && (3 == ccid_descriptor -> bNumEndpoints))
72 {
73 #ifndef TWIN_SERIAL
74 /* just wait for 100ms in case a notification is in the pipe */
75 (void)InterruptRead(reader_index, 100);
76 #endif
77 }
78
79 /* ICCD type A */
80 if (PROTOCOL_ICCD_A == ccid_descriptor->bInterfaceProtocol)
81 {
82 unsigned char tmp[MAX_ATR_SIZE];
83 unsigned int n = sizeof(tmp);
84
85 DEBUG_COMM("ICCD type A");
86 (void)CmdPowerOff(reader_index);
87 (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
88 (void)CmdPowerOff(reader_index);
89 }
90
91 /* ICCD type B */
92 if (PROTOCOL_ICCD_B == ccid_descriptor->bInterfaceProtocol)
93 {
94 unsigned char tmp[MAX_ATR_SIZE];
95 unsigned int n = sizeof(tmp);
96
97 DEBUG_COMM("ICCD type B");
98 if (CCID_CLASS_SHORT_APDU ==
99 (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK))
100 {
101 /* use the extended APDU comm alogorithm */
102 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
103 ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
104 }
105
106 (void)CmdPowerOff(reader_index);
107 (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
108 (void)CmdPowerOff(reader_index);
109 }
110
111 return 0;
112 } /* ccid_open_hack_pre */
113
114 #ifndef NO_LOG
115 /*****************************************************************************
116 *
117 * dump_gemalto_firmware_features
118 *
119 ****************************************************************************/
120 static void dump_gemalto_firmware_features(struct GEMALTO_FIRMWARE_FEATURES *gff)
121 {
122 DEBUG_INFO2("Dumping Gemalto firmware features (%zd bytes):",
123 sizeof(struct GEMALTO_FIRMWARE_FEATURES));
124
125 #define YESNO(x) (x) ? "yes" : "no"
126
127 DEBUG_INFO2(" bLogicalLCDLineNumber: %d", gff->bLogicalLCDLineNumber);
128 DEBUG_INFO2(" bLogicalLCDRowNumber: %d", gff->bLogicalLCDRowNumber);
129 DEBUG_INFO2(" bLcdInfo: 0x%02X", gff->bLcdInfo);
130 DEBUG_INFO2(" bEntryValidationCondition: 0x%02X",
131 gff->bEntryValidationCondition);
132
133 DEBUG_INFO(" Reader supports PC/SCv2 features:");
134 DEBUG_INFO2(" VerifyPinStart: %s", YESNO(gff->VerifyPinStart));
135 DEBUG_INFO2(" VerifyPinFinish: %s", YESNO(gff->VerifyPinFinish));
136 DEBUG_INFO2(" ModifyPinStart: %s", YESNO(gff->ModifyPinStart));
137 DEBUG_INFO2(" ModifyPinFinish: %s", YESNO(gff->ModifyPinFinish));
138 DEBUG_INFO2(" GetKeyPressed: %s", YESNO(gff->GetKeyPressed));
139 DEBUG_INFO2(" VerifyPinDirect: %s", YESNO(gff->VerifyPinDirect));
140 DEBUG_INFO2(" ModifyPinDirect: %s", YESNO(gff->ModifyPinDirect));
141 DEBUG_INFO2(" Abort: %s", YESNO(gff->Abort));
142 DEBUG_INFO2(" GetKey: %s", YESNO(gff->GetKey));
143 DEBUG_INFO2(" WriteDisplay: %s", YESNO(gff->WriteDisplay));
144 DEBUG_INFO2(" SetSpeMessage: %s", YESNO(gff->SetSpeMessage));
145 DEBUG_INFO2(" bTimeOut2: %s", YESNO(gff->bTimeOut2));
146 DEBUG_INFO2(" bPPDUSupportOverXferBlock: %s",
147 YESNO(gff->bPPDUSupportOverXferBlock));
148 DEBUG_INFO2(" bPPDUSupportOverEscape: %s",
149 YESNO(gff->bPPDUSupportOverEscape));
150
151 DEBUG_INFO2(" bListSupportedLanguages: %s",
152 YESNO(gff->bListSupportedLanguages));
153 DEBUG_INFO2(" bNumberMessageFix: %s", YESNO(gff->bNumberMessageFix));
154
155 DEBUG_INFO2(" VersionNumber: 0x%02X", gff->VersionNumber);
156 DEBUG_INFO2(" MinimumPINSize: %d", gff->MinimumPINSize);
157 DEBUG_INFO2(" MaximumPINSize: %d", gff->MaximumPINSize);
158 DEBUG_INFO2(" Firewall: %s", YESNO(gff->Firewall));
159 if (gff->Firewall && gff->FirewalledCommand_SW1
160 && gff->FirewalledCommand_SW2)
161 {
162 DEBUG_INFO2(" FirewalledCommand_SW1: 0x%02X",
163 gff->FirewalledCommand_SW1);
164 DEBUG_INFO2(" FirewalledCommand_SW2: 0x%02X",
165 gff->FirewalledCommand_SW2);
166 }
167
168 } /* dump_gemalto_firmware_features */
169 #endif
170
171 /*****************************************************************************
172 *
173 * set_gemalto_firmware_features
174 *
175 ****************************************************************************/
176 static void set_gemalto_firmware_features(unsigned int reader_index)
177 {
178 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
179 struct GEMALTO_FIRMWARE_FEATURES *gf_features;
180
181 gf_features = malloc(sizeof(struct GEMALTO_FIRMWARE_FEATURES));
182 if (gf_features)
183 {
184 unsigned char cmd[] = { 0x6A }; /* GET_FIRMWARE_FEATURES command id */
185 unsigned int len_features = sizeof *gf_features;
186 RESPONSECODE ret;
187
188 ret = CmdEscape(reader_index, cmd, sizeof cmd,
189 (unsigned char*)gf_features, &len_features);
190 if ((IFD_SUCCESS == ret) &&
191 (len_features == sizeof *gf_features))
192 {
193 /* Command is supported if it succeeds at CCID level */
194 /* and returned size matches our expectation */
195 ccid_descriptor->gemalto_firmware_features = gf_features;
196 #ifndef NO_LOG
197 dump_gemalto_firmware_features(gf_features);
198 #endif
199 }
200 else
201 {
202 /* Command is not supported, let's free allocated memory */
203 free(gf_features);
204 DEBUG_INFO3("GET_FIRMWARE_FEATURES failed: " DWORD_D ", len=%d",
205 ret, len_features);
206 }
207 }
208 } /* set_gemalto_firmware_features */
209
210 /*****************************************************************************
211 *
212 * ccid_open_hack_post
213 *
214 ****************************************************************************/
215 int ccid_open_hack_post(unsigned int reader_index)
216 {
217 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
218 RESPONSECODE return_value = IFD_SUCCESS;
219
220 switch (ccid_descriptor->readerID)
221 {
222 case GEMPCKEY:
223 case GEMPCTWIN:
224 /* Reader announces TPDU but can do APDU (EMV in fact) */
225 if (DriverOptions & DRIVER_OPTION_GEMPC_TWIN_KEY_APDU)
226 {
227 unsigned char cmd[] = { 0x1F, 0x02 };
228 unsigned char res[10];
229 unsigned int length_res = sizeof(res);
230
231 if (CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res) == IFD_SUCCESS)
232 {
233 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
234 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
235 }
236 }
237 break;
238
239 case VEGAALPHA:
240 case GEMPCPINPAD:
241 /* load the l10n strings in the pinpad memory */
242 {
243 #define L10N_HEADER_SIZE 5
244 #define L10N_STRING_MAX_SIZE 16
245 #define L10N_NB_STRING 10
246
247 unsigned char cmd[L10N_HEADER_SIZE + L10N_NB_STRING * L10N_STRING_MAX_SIZE];
248 unsigned char res[20];
249 unsigned int length_res = sizeof(res);
250 int offset, i, j;
251
252 const char *fr[] = {
253 "Entrer PIN",
254 "Nouveau PIN",
255 "Confirmer PIN",
256 "PIN correct",
257 "PIN Incorrect !",
258 "Delai depasse",
259 "* essai restant",
260 "Inserer carte",
261 "Erreur carte",
262 "PIN bloque" };
263
264 const char *de[] = {
265 "PIN eingeben",
266 "Neue PIN",
267 "PIN bestatigen",
268 "PIN korrect",
269 "Falsche PIN !",
270 "Zeit abgelaufen",
271 "* Versuche ubrig",
272 "Karte einstecken",
273 "Fehler Karte",
274 "PIN blockiert" };
275
276 const char *es[] = {
277 "Introducir PIN",
278 "Nuevo PIN",
279 "Confirmar PIN",
280 "PIN OK",
281 "PIN Incorrecto !",
282 "Tiempo Agotado",
283 "* ensayos quedan",
284 "Introducir Tarj.",
285 "Error en Tarjeta",
286 "PIN bloqueado" };
287
288 const char *it[] = {
289 "Inserire PIN",
290 "Nuovo PIN",
291 "Confermare PIN",
292 "PIN Corretto",
293 "PIN Errato !",
294 "Tempo scaduto",
295 "* prove rimaste",
296 "Inserire Carta",
297 "Errore Carta",
298 "PIN ostruito"};
299
300 const char *pt[] = {
301 "Insira PIN",
302 "Novo PIN",
303 "Conf. novo PIN",
304 "PIN OK",
305 "PIN falhou!",
306 "Tempo expirou",
307 "* tentiv. restam",
308 "Introduza cartao",
309 "Erro cartao",
310 "PIN bloqueado" };
311
312 const char *nl[] = {
313 "Inbrengen code",
314 "Nieuwe code",
315 "Bevestig code",
316 "Code aanvaard",
317 "Foute code",
318 "Time out",
319 "* Nog Pogingen",
320 "Kaart inbrengen",
321 "Kaart fout",
322 "Kaart blok" };
323
324 const char *tr[] = {
325 "PIN Giriniz",
326 "Yeni PIN",
327 "PIN Onayala",
328 "PIN OK",
329 "Yanlis PIN",
330 "Zaman Asimi",
331 "* deneme kaldi",
332 "Karti Takiniz",
333 "Kart Hatasi",
334 "Kart Kilitli" };
335
336 const char *en[] = {
337 "Enter PIN",
338 "New PIN",
339 "Confirm PIN",
340 "PIN OK",
341 "Incorrect PIN!",
342 "Time Out",
343 "* retries left",
344 "Insert Card",
345 "Card Error",
346 "PIN blocked" };
347
348 const char *lang;
349 const char **l10n;
350
351 #ifdef __APPLE__
352 CFArrayRef cfa;
353 CFStringRef slang;
354
355 /* Get the complete ordered list */
356 cfa = CFLocaleCopyPreferredLanguages();
357
358 /* Use the first/preferred language
359 * As the driver is run as root we get the language
360 * selected during install */
361 slang = CFArrayGetValueAtIndex(cfa, 0);
362
363 /* CFString -> C string */
364 lang = CFStringGetCStringPtr(slang, kCFStringEncodingMacRoman);
365 #else
366 /* The other Unixes just use the LANG env variable */
367 lang = getenv("LANG");
368 #endif
369 DEBUG_COMM2("Using lang: %s", lang);
370 if (NULL == lang)
371 l10n = en;
372 else
373 {
374 if (0 == strncmp(lang, "fr", 2))
375 l10n = fr;
376 else if (0 == strncmp(lang, "de", 2))
377 l10n = de;
378 else if (0 == strncmp(lang, "es", 2))
379 l10n = es;
380 else if (0 == strncmp(lang, "it", 2))
381 l10n = it;
382 else if (0 == strncmp(lang, "pt", 2))
383 l10n = pt;
384 else if (0 == strncmp(lang, "nl", 2))
385 l10n = nl;
386 else if (0 == strncmp(lang, "tr", 2))
387 l10n = tr;
388 else
389 l10n = en;
390 }
391
392 #ifdef __APPLE__
393 /* Release the allocated array */
394 CFRelease(cfa);
395 #endif
396 offset = 0;
397 cmd[offset++] = 0xB2; /* load strings */
398 cmd[offset++] = 0xA0; /* address of the memory */
399 cmd[offset++] = 0x00; /* address of the first byte */
400 cmd[offset++] = 0x4D; /* magic value */
401 cmd[offset++] = 0x4C; /* magic value */
402
403 /* for each string */
404 for (i=0; i<L10N_NB_STRING; i++)
405 {
406 /* copy the string */
407 for (j=0; l10n[i][j]; j++)
408 cmd[offset++] = l10n[i][j];
409
410 /* pad with " " */
411 for (; j<L10N_STRING_MAX_SIZE; j++)
412 cmd[offset++] = ' ';
413 }
414
415 (void)sleep(1);
416 if (IFD_SUCCESS == CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res))
417 {
418 DEBUG_COMM("l10n string loaded successfully");
419 }
420 else
421 {
422 DEBUG_COMM("Failed to load l10n strings");
423 return_value = IFD_COMMUNICATION_ERROR;
424 }
425 }
426 break;
427
428 case HPSMARTCARDKEYBOARD:
429 case HP_CCIDSMARTCARDKEYBOARD:
430 /* the Secure Pin Entry is bogus so disable it
431 * http://martinpaljak.net/2011/03/19/insecure-hp-usb-smart-card-keyboard/
432 */
433 ccid_descriptor->bPINSupport = 0;
434 break;
435
436 #if 0
437 /* SCM SCR331-DI contactless */
438 case SCR331DI:
439 /* SCM SCR331-DI-NTTCOM contactless */
440 case SCR331DINTTCOM:
441 /* SCM SDI010 contactless */
442 case SDI010:
443 /* the contactless reader is in the second slot */
444 if (ccid_descriptor->bCurrentSlotIndex > 0)
445 {
446 unsigned char cmd1[] = { 0x00 };
447 /* command: 00 ??
448 * response: 06 10 03 03 00 00 00 01 FE FF FF FE 01 ?? */
449 unsigned char cmd2[] = { 0x02 };
450 /* command: 02 ??
451 * response: 00 ?? */
452
453 unsigned char res[20];
454 unsigned int length_res = sizeof(res);
455
456 if ((IFD_SUCCESS == CmdEscape(reader_index, cmd1, sizeof(cmd1), res, &length_res))
457 && (IFD_SUCCESS == CmdEscape(reader_index, cmd2, sizeof(cmd2), res, &length_res)))
458 {
459 DEBUG_COMM("SCM SCR331-DI contactless detected");
460 }
461 else
462 {
463 DEBUG_COMM("SCM SCR331-DI contactless init failed");
464 }
465
466 /* hack since the contactless reader do not share dwFeatures */
467 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
468 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
469
470 ccid_descriptor->dwFeatures |= CCID_CLASS_AUTO_IFSD;
471 }
472 break;
473 #endif
474 }
475
476 /* Gemalto readers may report additional information */
477 if (GET_VENDOR(ccid_descriptor->readerID) == VENDOR_GEMALTO)
478 set_gemalto_firmware_features(reader_index);
479
480 return return_value;
481 } /* ccid_open_hack_post */
482
483 /*****************************************************************************
484 *
485 * ccid_error
486 *
487 ****************************************************************************/
488 void ccid_error(int error, const char *file, int line, const char *function)
489 {
490 const char *text;
491 char var_text[30];
492
493 switch (error)
494 {
495 case 0x00:
496 text = "Command not supported or not allowed";
497 break;
498
499 case 0x01:
500 text = "Wrong command length";
501 break;
502
503 case 0x05:
504 text = "Invalid slot number";
505 break;
506
507 case 0xA2:
508 text = "Card short-circuiting. Card powered off";
509 break;
510
511 case 0xA3:
512 text = "ATR too long (> 33)";
513 break;
514
515 case 0xAB:
516 text = "No data exchanged";
517 break;
518
519 case 0xB0:
520 text = "Reader in EMV mode and T=1 message too long";
521 break;
522
523 case 0xBB:
524 text = "Protocol error in EMV mode";
525 break;
526
527 case 0xBD:
528 text = "Card error during T=1 exchange";
529 break;
530
531 case 0xBE:
532 text = "Wrong APDU command length";
533 break;
534
535 case 0xE0:
536 text = "Slot busy";
537 break;
538
539 case 0xEF:
540 text = "PIN cancelled";
541 break;
542
543 case 0xF0:
544 text = "PIN timeout";
545 break;
546
547 case 0xF2:
548 text = "Busy with autosequence";
549 break;
550
551 case 0xF3:
552 text = "Deactivated protocol";
553 break;
554
555 case 0xF4:
556 text = "Procedure byte conflict";
557 break;
558
559 case 0xF5:
560 text = "Class not supported";
561 break;
562
563 case 0xF6:
564 text = "Protocol not supported";
565 break;
566
567 case 0xF7:
568 text = "Invalid ATR checksum byte (TCK)";
569 break;
570
571 case 0xF8:
572 text = "Invalid ATR first byte";
573 break;
574
575 case 0xFB:
576 text = "Hardware error";
577 break;
578
579 case 0xFC:
580 text = "Overrun error";
581 break;
582
583 case 0xFD:
584 text = "Parity error during exchange";
585 break;
586
587 case 0xFE:
588 text = "Card absent or mute";
589 break;
590
591 case 0xFF:
592 text = "Activity aborted by Host";
593 break;
594
595 default:
596 if ((error >= 1) && (error <= 127))
597 (void)snprintf(var_text, sizeof(var_text), "error on byte %d",
598 error);
599 else
600 (void)snprintf(var_text, sizeof(var_text),
601 "Unknown CCID error: 0x%02X", error);
602
603 text = var_text;
604 break;
605 }
606 log_msg(PCSC_LOG_ERROR, "%s:%d:%s %s", file, line, function, text);
607
608 } /* ccid_error */
609

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5