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