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