Blame src/ccid.c

Packit Service aee942
/*
Packit Service aee942
    ccid.c: CCID common code
Packit Service aee942
    Copyright (C) 2003-2010   Ludovic Rousseau
Packit Service aee942
Packit Service aee942
    This library is free software; you can redistribute it and/or
Packit Service aee942
    modify it under the terms of the GNU Lesser General Public
Packit Service aee942
    License as published by the Free Software Foundation; either
Packit Service aee942
    version 2.1 of the License, or (at your option) any later version.
Packit Service aee942
Packit Service aee942
    This library is distributed in the hope that it will be useful,
Packit Service aee942
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service aee942
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service aee942
    Lesser General Public License for more details.
Packit Service aee942
Packit Service aee942
	You should have received a copy of the GNU Lesser General Public License
Packit Service aee942
	along with this library; if not, write to the Free Software Foundation,
Packit Service aee942
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service aee942
*/
Packit Service aee942
Packit Service aee942
#include <config.h>
Packit Service aee942
Packit Service aee942
#ifdef HAVE_STDIO_H
Packit Service aee942
#include <stdio.h>
Packit Service aee942
#endif
Packit Service aee942
#ifdef HAVE_STDLIB_H
Packit Service aee942
#include <stdlib.h>
Packit Service aee942
#endif
Packit Service aee942
#ifdef HAVE_STRING_H
Packit Service aee942
#include <string.h>
Packit Service aee942
#endif
Packit Service aee942
#ifdef HAVE_UNISTD_H
Packit Service aee942
#include <unistd.h>
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
#include <pcsclite.h>
Packit Service aee942
#include <ifdhandler.h>
Packit Service aee942
Packit Service aee942
#include "debug.h"
Packit Service aee942
#include "ccid.h"
Packit Service aee942
#include "defs.h"
Packit Service aee942
#include "ccid_ifdhandler.h"
Packit Service aee942
#include "commands.h"
Packit Service aee942
#include "utils.h"
Packit Service aee942
Packit Service aee942
#ifdef __APPLE__
Packit Service aee942
#include <CoreFoundation/CoreFoundation.h>
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					ccid_open_hack_pre
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
int ccid_open_hack_pre(unsigned int reader_index)
Packit Service aee942
{
Packit Service aee942
	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
Packit Service aee942
Packit Service aee942
	switch (ccid_descriptor->readerID)
Packit Service aee942
	{
Packit Service aee942
		case MYSMARTPAD:
Packit Service aee942
			ccid_descriptor->dwMaxIFSD = 254;
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case CL1356D:
Packit Service aee942
			/* the firmware needs some time to initialize */
Packit Service aee942
			(void)sleep(1);
Packit Service aee942
			ccid_descriptor->readTimeout = 60*1000; /* 60 seconds */
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
#ifdef ENABLE_ZLP
Packit Service aee942
		case GEMPCTWIN:
Packit Service aee942
		case GEMPCKEY:
Packit Service aee942
		case DELLSCRK:
Packit Service aee942
			/* Only the chipset with firmware version 2.00 is "bogus"
Packit Service aee942
			 * The reader may send packets of 0 bytes when the reader is
Packit Service aee942
			 * connected to a USB 3 port */
Packit Service aee942
			if (0x0200 == ccid_descriptor->IFD_bcdDevice)
Packit Service aee942
			{
Packit Service aee942
				ccid_descriptor->zlp = TRUE;
Packit Service aee942
				DEBUG_INFO1("ZLP fixup");
Packit Service aee942
			}
Packit Service aee942
			break;
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
		case OZ776:
Packit Service aee942
		case OZ776_7772:
Packit Service aee942
			ccid_descriptor->dwMaxDataRate = 9600;
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case ElatecTWN4_CCID_CDC:
Packit Service aee942
		case ElatecTWN4_CCID:
Packit Service aee942
			/* Use a timeout of 1000 ms instead of 100 ms in
Packit Service aee942
			 * CmdGetSlotStatus() used by CreateChannelByNameOrChannel()
Packit Service aee942
			 * The reader answers after up to 1 s if no tag is present */
Packit Service aee942
			ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT * 10;
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case SCM_SCL011:
Packit Service aee942
			/* The SCM SCL011 reader needs 350 ms to answer */
Packit Service aee942
			ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT * 4;
Packit Service aee942
			break;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* CCID */
Packit Service aee942
	if ((PROTOCOL_CCID == ccid_descriptor->bInterfaceProtocol)
Packit Service aee942
		&& (3 == ccid_descriptor -> bNumEndpoints))
Packit Service aee942
	{
Packit Service aee942
#ifndef TWIN_SERIAL
Packit Service aee942
		/* just wait for 100ms in case a notification is in the pipe */
Packit Service aee942
		(void)InterruptRead(reader_index, 100);
Packit Service aee942
#endif
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* ICCD type A */
Packit Service aee942
	if (PROTOCOL_ICCD_A == ccid_descriptor->bInterfaceProtocol)
Packit Service aee942
	{
Packit Service aee942
		unsigned char tmp[MAX_ATR_SIZE];
Packit Service aee942
		unsigned int n = sizeof(tmp);
Packit Service aee942
Packit Service aee942
		DEBUG_COMM("ICCD type A");
Packit Service aee942
		(void)CmdPowerOff(reader_index);
Packit Service aee942
		(void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
Packit Service aee942
		(void)CmdPowerOff(reader_index);
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* ICCD type B */
Packit Service aee942
	if (PROTOCOL_ICCD_B == ccid_descriptor->bInterfaceProtocol)
Packit Service aee942
	{
Packit Service aee942
		unsigned char tmp[MAX_ATR_SIZE];
Packit Service aee942
		unsigned int n = sizeof(tmp);
Packit Service aee942
Packit Service aee942
		DEBUG_COMM("ICCD type B");
Packit Service aee942
		if (CCID_CLASS_SHORT_APDU ==
Packit Service aee942
			(ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK))
Packit Service aee942
		{
Packit Service aee942
			/* use the extended APDU comm alogorithm */
Packit Service aee942
			ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
Packit Service aee942
			ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		(void)CmdPowerOff(reader_index);
Packit Service aee942
		(void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
Packit Service aee942
		(void)CmdPowerOff(reader_index);
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	return 0;
Packit Service aee942
} /* ccid_open_hack_pre */
Packit Service aee942
Packit Service aee942
#ifndef NO_LOG
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					dump_gemalto_firmware_features
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
static void dump_gemalto_firmware_features(struct GEMALTO_FIRMWARE_FEATURES *gff)
Packit Service aee942
{
Packit Service aee942
	DEBUG_INFO2("Dumping Gemalto firmware features (%zd bytes):",
Packit Service aee942
		sizeof(struct GEMALTO_FIRMWARE_FEATURES));
Packit Service aee942
Packit Service aee942
#define YESNO(x) (x) ? "yes" : "no"
Packit Service aee942
Packit Service aee942
	DEBUG_INFO2(" bLogicalLCDLineNumber: %d", gff->bLogicalLCDLineNumber);
Packit Service aee942
	DEBUG_INFO2(" bLogicalLCDRowNumber: %d", gff->bLogicalLCDRowNumber);
Packit Service aee942
	DEBUG_INFO2(" bLcdInfo: 0x%02X", gff->bLcdInfo);
Packit Service aee942
	DEBUG_INFO2(" bEntryValidationCondition: 0x%02X",
Packit Service aee942
		gff->bEntryValidationCondition);
Packit Service aee942
Packit Service aee942
	DEBUG_INFO1(" Reader supports PC/SCv2 features:");
Packit Service aee942
	DEBUG_INFO2("  VerifyPinStart: %s", YESNO(gff->VerifyPinStart));
Packit Service aee942
	DEBUG_INFO2("  VerifyPinFinish: %s", YESNO(gff->VerifyPinFinish));
Packit Service aee942
	DEBUG_INFO2("  ModifyPinStart: %s", YESNO(gff->ModifyPinStart));
Packit Service aee942
	DEBUG_INFO2("  ModifyPinFinish: %s", YESNO(gff->ModifyPinFinish));
Packit Service aee942
	DEBUG_INFO2("  GetKeyPressed: %s", YESNO(gff->GetKeyPressed));
Packit Service aee942
	DEBUG_INFO2("  VerifyPinDirect: %s", YESNO(gff->VerifyPinDirect));
Packit Service aee942
	DEBUG_INFO2("  ModifyPinDirect: %s", YESNO(gff->ModifyPinDirect));
Packit Service aee942
	DEBUG_INFO2("  Abort: %s", YESNO(gff->Abort));
Packit Service aee942
	DEBUG_INFO2("  GetKey: %s", YESNO(gff->GetKey));
Packit Service aee942
	DEBUG_INFO2("  WriteDisplay: %s", YESNO(gff->WriteDisplay));
Packit Service aee942
	DEBUG_INFO2("  SetSpeMessage: %s", YESNO(gff->SetSpeMessage));
Packit Service aee942
	DEBUG_INFO2("  bTimeOut2: %s", YESNO(gff->bTimeOut2));
Packit Service aee942
	DEBUG_INFO2("  bPPDUSupportOverXferBlock: %s",
Packit Service aee942
		YESNO(gff->bPPDUSupportOverXferBlock));
Packit Service aee942
	DEBUG_INFO2("  bPPDUSupportOverEscape: %s",
Packit Service aee942
		YESNO(gff->bPPDUSupportOverEscape));
Packit Service aee942
Packit Service aee942
	DEBUG_INFO2(" bListSupportedLanguages: %s",
Packit Service aee942
		YESNO(gff->bListSupportedLanguages));
Packit Service aee942
	DEBUG_INFO2(" bNumberMessageFix: %s", YESNO(gff->bNumberMessageFix));
Packit Service aee942
Packit Service aee942
	DEBUG_INFO2(" VersionNumber: 0x%02X", gff->VersionNumber);
Packit Service aee942
	DEBUG_INFO2(" MinimumPINSize: %d", gff->MinimumPINSize);
Packit Service aee942
	DEBUG_INFO2(" MaximumPINSize: %d", gff->MaximumPINSize);
Packit Service aee942
	DEBUG_INFO2(" Firewall: %s", YESNO(gff->Firewall));
Packit Service aee942
	if (gff->Firewall && gff->FirewalledCommand_SW1
Packit Service aee942
		&& gff->FirewalledCommand_SW2)
Packit Service aee942
	{
Packit Service aee942
		DEBUG_INFO2("  FirewalledCommand_SW1: 0x%02X",
Packit Service aee942
			gff->FirewalledCommand_SW1);
Packit Service aee942
		DEBUG_INFO2("  FirewalledCommand_SW2: 0x%02X",
Packit Service aee942
			gff->FirewalledCommand_SW2);
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
} /* dump_gemalto_firmware_features */
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					set_gemalto_firmware_features
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
static void set_gemalto_firmware_features(unsigned int reader_index)
Packit Service aee942
{
Packit Service aee942
	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
Packit Service aee942
	struct GEMALTO_FIRMWARE_FEATURES *gf_features;
Packit Service aee942
Packit Service aee942
	gf_features = malloc(sizeof(struct GEMALTO_FIRMWARE_FEATURES));
Packit Service aee942
	if (gf_features)
Packit Service aee942
	{
Packit Service aee942
		unsigned char cmd[] = { 0x6A }; /* GET_FIRMWARE_FEATURES command id */
Packit Service aee942
		unsigned int len_features = sizeof *gf_features;
Packit Service aee942
		RESPONSECODE ret;
Packit Service aee942
Packit Service aee942
		ret = CmdEscapeCheck(reader_index, cmd, sizeof cmd,
Packit Service aee942
			(unsigned char*)gf_features, &len_features, 0, TRUE);
Packit Service aee942
		if ((IFD_SUCCESS == ret) &&
Packit Service aee942
		    (len_features == sizeof *gf_features))
Packit Service aee942
		{
Packit Service aee942
			/* Command is supported if it succeeds at CCID level */
Packit Service aee942
			/* and returned size matches our expectation */
Packit Service aee942
			ccid_descriptor->gemalto_firmware_features = gf_features;
Packit Service aee942
#ifndef NO_LOG
Packit Service aee942
			dump_gemalto_firmware_features(gf_features);
Packit Service aee942
#endif
Packit Service aee942
		}
Packit Service aee942
		else
Packit Service aee942
		{
Packit Service aee942
			/* Command is not supported, let's free allocated memory */
Packit Service aee942
			free(gf_features);
Packit Service aee942
			DEBUG_INFO3("GET_FIRMWARE_FEATURES failed: " DWORD_D ", len=%d",
Packit Service aee942
				ret, len_features);
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
} /* set_gemalto_firmware_features */
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					ccid_open_hack_post
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
int ccid_open_hack_post(unsigned int reader_index)
Packit Service aee942
{
Packit Service aee942
	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
Packit Service aee942
	RESPONSECODE return_value = IFD_SUCCESS;
Packit Service aee942
Packit Service aee942
	switch (ccid_descriptor->readerID)
Packit Service aee942
	{
Packit Service aee942
		case GEMPCKEY:
Packit Service aee942
		case GEMPCTWIN:
Packit Service aee942
			/* Reader announces TPDU but can do APDU (EMV in fact) */
Packit Service aee942
			if (DriverOptions & DRIVER_OPTION_GEMPC_TWIN_KEY_APDU)
Packit Service aee942
			{
Packit Service aee942
				unsigned char cmd[] = { 0x1F, 0x02 };
Packit Service aee942
				unsigned char res[10];
Packit Service aee942
				unsigned int length_res = sizeof(res);
Packit Service aee942
Packit Service aee942
				if (CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res, 0) == IFD_SUCCESS)
Packit Service aee942
				{
Packit Service aee942
					ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
Packit Service aee942
					ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
Packit Service aee942
				}
Packit Service aee942
			}
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case VEGAALPHA:
Packit Service aee942
		case GEMPCPINPAD:
Packit Service aee942
			/* load the l10n strings in the pinpad memory */
Packit Service aee942
			{
Packit Service aee942
#define L10N_HEADER_SIZE 5
Packit Service aee942
#define L10N_STRING_MAX_SIZE 16
Packit Service aee942
#define L10N_NB_STRING 10
Packit Service aee942
Packit Service aee942
				unsigned char cmd[L10N_HEADER_SIZE + L10N_NB_STRING * L10N_STRING_MAX_SIZE];
Packit Service aee942
				unsigned char res[20];
Packit Service aee942
				unsigned int length_res = sizeof(res);
Packit Service aee942
				int offset, i, j;
Packit Service aee942
Packit Service aee942
				const char *fr[] = {
Packit Service aee942
					"Entrer PIN",
Packit Service aee942
					"Nouveau PIN",
Packit Service aee942
					"Confirmer PIN",
Packit Service aee942
					"PIN correct",
Packit Service aee942
					"PIN Incorrect !",
Packit Service aee942
					"Delai depasse",
Packit Service aee942
					"* essai restant",
Packit Service aee942
					"Inserer carte",
Packit Service aee942
					"Erreur carte",
Packit Service aee942
					"PIN bloque" };
Packit Service aee942
Packit Service aee942
				const char *de[] = {
Packit Service aee942
					"PIN eingeben",
Packit Service aee942
					"Neue PIN",
Packit Service aee942
					"PIN bestatigen",
Packit Service aee942
					"PIN korrect",
Packit Service aee942
					"Falsche PIN !",
Packit Service aee942
					"Zeit abgelaufen",
Packit Service aee942
					"* Versuche ubrig",
Packit Service aee942
					"Karte einstecken",
Packit Service aee942
					"Fehler Karte",
Packit Service aee942
					"PIN blockiert" };
Packit Service aee942
Packit Service aee942
				const char *es[] = {
Packit Service aee942
					"Introducir PIN",
Packit Service aee942
					"Nuevo PIN",
Packit Service aee942
					"Confirmar PIN",
Packit Service aee942
					"PIN OK",
Packit Service aee942
					"PIN Incorrecto !",
Packit Service aee942
					"Tiempo Agotado",
Packit Service aee942
					"* ensayos quedan",
Packit Service aee942
					"Introducir Tarj.",
Packit Service aee942
					"Error en Tarjeta",
Packit Service aee942
					"PIN bloqueado" };
Packit Service aee942
Packit Service aee942
				const char *it[] = {
Packit Service aee942
					"Inserire PIN",
Packit Service aee942
					"Nuovo PIN",
Packit Service aee942
					"Confermare PIN",
Packit Service aee942
					"PIN Corretto",
Packit Service aee942
					"PIN Errato !",
Packit Service aee942
					"Tempo scaduto",
Packit Service aee942
					"* prove rimaste",
Packit Service aee942
					"Inserire Carta",
Packit Service aee942
					"Errore Carta",
Packit Service aee942
					"PIN ostruito"};
Packit Service aee942
Packit Service aee942
				const char *pt[] = {
Packit Service aee942
					"Insira PIN",
Packit Service aee942
					"Novo PIN",
Packit Service aee942
					"Conf. novo PIN",
Packit Service aee942
					"PIN OK",
Packit Service aee942
					"PIN falhou!",
Packit Service aee942
					"Tempo expirou",
Packit Service aee942
					"* tentiv. restam",
Packit Service aee942
					"Introduza cartao",
Packit Service aee942
					"Erro cartao",
Packit Service aee942
					"PIN bloqueado" };
Packit Service aee942
Packit Service aee942
				const char *nl[] = {
Packit Service aee942
					"Inbrengen code",
Packit Service aee942
					"Nieuwe code",
Packit Service aee942
					"Bevestig code",
Packit Service aee942
					"Code aanvaard",
Packit Service aee942
					"Foute code",
Packit Service aee942
					"Time out",
Packit Service aee942
					"* Nog Pogingen",
Packit Service aee942
					"Kaart inbrengen",
Packit Service aee942
					"Kaart fout",
Packit Service aee942
					"Kaart blok" };
Packit Service aee942
Packit Service aee942
				const char *tr[] = {
Packit Service aee942
					"PIN Giriniz",
Packit Service aee942
					"Yeni PIN",
Packit Service aee942
					"PIN Onayala",
Packit Service aee942
					"PIN OK",
Packit Service aee942
					"Yanlis PIN",
Packit Service aee942
					"Zaman Asimi",
Packit Service aee942
					"* deneme kaldi",
Packit Service aee942
					"Karti Takiniz",
Packit Service aee942
					"Kart Hatasi",
Packit Service aee942
					"Kart Kilitli" };
Packit Service aee942
Packit Service aee942
				const char *en[] = {
Packit Service aee942
					"Enter PIN",
Packit Service aee942
					"New PIN",
Packit Service aee942
					"Confirm PIN",
Packit Service aee942
					"PIN OK",
Packit Service aee942
					"Incorrect PIN!",
Packit Service aee942
					"Time Out",
Packit Service aee942
					"* retries left",
Packit Service aee942
					"Insert Card",
Packit Service aee942
					"Card Error",
Packit Service aee942
					"PIN blocked" };
Packit Service aee942
Packit Service aee942
				const char *lang;
Packit Service aee942
				const char **l10n;
Packit Service aee942
Packit Service aee942
#ifdef __APPLE__
Packit Service aee942
				CFArrayRef cfa;
Packit Service aee942
				CFStringRef slang;
Packit Service aee942
Packit Service aee942
				/* Get the complete ordered list */
Packit Service aee942
				cfa = CFLocaleCopyPreferredLanguages();
Packit Service aee942
Packit Service aee942
				/* Use the first/preferred language
Packit Service aee942
				 * As the driver is run as root we get the language
Packit Service aee942
				 * selected during install */
Packit Service aee942
				slang = CFArrayGetValueAtIndex(cfa, 0);
Packit Service aee942
Packit Service aee942
				/* CFString -> C string */
Packit Service aee942
				lang = CFStringGetCStringPtr(slang, kCFStringEncodingMacRoman);
Packit Service aee942
#else
Packit Service aee942
				/* The other Unixes just use the LANG env variable */
Packit Service aee942
				lang = getenv("LANG");
Packit Service aee942
#endif
Packit Service aee942
				DEBUG_COMM2("Using lang: %s", lang);
Packit Service aee942
				if (NULL == lang)
Packit Service aee942
					l10n = en;
Packit Service aee942
				else
Packit Service aee942
				{
Packit Service aee942
					if (0 == strncmp(lang, "fr", 2))
Packit Service aee942
						l10n = fr;
Packit Service aee942
					else if (0 == strncmp(lang, "de", 2))
Packit Service aee942
						l10n = de;
Packit Service aee942
					else if (0 == strncmp(lang, "es", 2))
Packit Service aee942
						l10n = es;
Packit Service aee942
					else if (0 == strncmp(lang, "it", 2))
Packit Service aee942
						l10n = it;
Packit Service aee942
					else if (0 == strncmp(lang, "pt", 2))
Packit Service aee942
						l10n = pt;
Packit Service aee942
					else if (0 == strncmp(lang, "nl", 2))
Packit Service aee942
						l10n = nl;
Packit Service aee942
					else if (0 == strncmp(lang, "tr", 2))
Packit Service aee942
						l10n = tr;
Packit Service aee942
					else
Packit Service aee942
						l10n = en;
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
#ifdef __APPLE__
Packit Service aee942
				/* Release the allocated array */
Packit Service aee942
				CFRelease(cfa);
Packit Service aee942
#endif
Packit Service aee942
				offset = 0;
Packit Service aee942
				cmd[offset++] = 0xB2;	/* load strings */
Packit Service aee942
				cmd[offset++] = 0xA0;	/* address of the memory */
Packit Service aee942
				cmd[offset++] = 0x00;	/* address of the first byte */
Packit Service aee942
				cmd[offset++] = 0x4D;	/* magic value */
Packit Service aee942
				cmd[offset++] = 0x4C;	/* magic value */
Packit Service aee942
Packit Service aee942
				/* for each string */
Packit Service aee942
				for (i=0; i
Packit Service aee942
				{
Packit Service aee942
					/* copy the string */
Packit Service aee942
					for (j=0; l10n[i][j]; j++)
Packit Service aee942
						cmd[offset++] = l10n[i][j];
Packit Service aee942
Packit Service aee942
					/* pad with " " */
Packit Service aee942
					for (; j
Packit Service aee942
						cmd[offset++] = ' ';
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
				(void)sleep(1);
Packit Service aee942
				if (IFD_SUCCESS == CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res, DEFAULT_COM_READ_TIMEOUT))
Packit Service aee942
				{
Packit Service aee942
					DEBUG_COMM("l10n string loaded successfully");
Packit Service aee942
				}
Packit Service aee942
				else
Packit Service aee942
				{
Packit Service aee942
					DEBUG_COMM("Failed to load l10n strings");
Packit Service aee942
					return_value = IFD_COMMUNICATION_ERROR;
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
				if (DriverOptions & DRIVER_OPTION_DISABLE_PIN_RETRIES)
Packit Service aee942
				{
Packit Service aee942
					/* disable VERIFY from reader */
Packit Service aee942
					const unsigned char cmd2[] = {0xb5, 0x00};
Packit Service aee942
					length_res = sizeof(res);
Packit Service aee942
					if (IFD_SUCCESS == CmdEscape(reader_index, cmd2, sizeof(cmd2), res, &length_res, DEFAULT_COM_READ_TIMEOUT))
Packit Service aee942
					{
Packit Service aee942
						DEBUG_COMM("Disable SPE retry counter successful");
Packit Service aee942
					}
Packit Service aee942
					else
Packit Service aee942
					{
Packit Service aee942
						DEBUG_CRITICAL("Failed to disable SPE retry counter");
Packit Service aee942
					}
Packit Service aee942
				}
Packit Service aee942
			}
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case HPSMARTCARDKEYBOARD:
Packit Service aee942
		case HP_CCIDSMARTCARDKEYBOARD:
Packit Service aee942
		case FUJITSUSMARTKEYB:
Packit Service aee942
			/* the Secure Pin Entry is bogus so disable it
Packit Service aee942
			 * https://web.archive.org/web/20120320001756/http://martinpaljak.net/2011/03/19/insecure-hp-usb-smart-card-keyboard/
Packit Service aee942
			 *
Packit Service aee942
			 * The problem is that the PIN code entered using the Secure
Packit Service aee942
			 * Pin Entry function is also sent to the host.
Packit Service aee942
			 */
Packit Service aee942
Packit Service aee942
		case C3PO_LTC31_v2:
Packit Service aee942
			ccid_descriptor->bPINSupport = 0;
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case HID_AVIATOR:      /* OMNIKEY Generic */
Packit Service aee942
		case HID_OMNIKEY_3X21: /* OMNIKEY 3121 or 3021 or 1021 */
Packit Service aee942
		case HID_OMNIKEY_6121: /* OMNIKEY 6121 */
Packit Service aee942
		case CHERRY_XX44:      /* Cherry Smart Terminal xx44 */
Packit Service aee942
		case FUJITSU_D323:     /* Fujitsu Smartcard Reader D323 */
Packit Service aee942
			/* The chip advertises pinpad but actually doesn't have one */
Packit Service aee942
			ccid_descriptor->bPINSupport = 0;
Packit Service aee942
			/* Firmware uses chaining */
Packit Service aee942
			ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
Packit Service aee942
			ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
#if 0
Packit Service aee942
		/* SCM SCR331-DI contactless */
Packit Service aee942
		case SCR331DI:
Packit Service aee942
		/* SCM SCR331-DI-NTTCOM contactless */
Packit Service aee942
		case SCR331DINTTCOM:
Packit Service aee942
		/* SCM SDI010 contactless */
Packit Service aee942
		case SDI010:
Packit Service aee942
			/* the contactless reader is in the second slot */
Packit Service aee942
			if (ccid_descriptor->bCurrentSlotIndex > 0)
Packit Service aee942
			{
Packit Service aee942
				unsigned char cmd1[] = { 0x00 };
Packit Service aee942
				/*  command: 00 ??
Packit Service aee942
				 * response: 06 10 03 03 00 00 00 01 FE FF FF FE 01 ?? */
Packit Service aee942
				unsigned char cmd2[] = { 0x02 };
Packit Service aee942
				/*  command: 02 ??
Packit Service aee942
				 * response: 00 ?? */
Packit Service aee942
Packit Service aee942
				unsigned char res[20];
Packit Service aee942
				unsigned int length_res = sizeof(res);
Packit Service aee942
Packit Service aee942
				if ((IFD_SUCCESS == CmdEscape(reader_index, cmd1, sizeof(cmd1), res, &length_res, 0))
Packit Service aee942
					&& (IFD_SUCCESS == CmdEscape(reader_index, cmd2, sizeof(cmd2), res, &length_res, 0)))
Packit Service aee942
				{
Packit Service aee942
					DEBUG_COMM("SCM SCR331-DI contactless detected");
Packit Service aee942
				}
Packit Service aee942
				else
Packit Service aee942
				{
Packit Service aee942
					DEBUG_COMM("SCM SCR331-DI contactless init failed");
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
				/* hack since the contactless reader do not share dwFeatures */
Packit Service aee942
				ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
Packit Service aee942
				ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
Packit Service aee942
Packit Service aee942
				ccid_descriptor->dwFeatures |= CCID_CLASS_AUTO_IFSD;
Packit Service aee942
			}
Packit Service aee942
			break;
Packit Service aee942
#endif
Packit Service aee942
		case CHERRY_KC1000SC:
Packit Service aee942
			if ((0x0100 == ccid_descriptor->IFD_bcdDevice)
Packit Service aee942
				&& (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK) == CCID_CLASS_SHORT_APDU)
Packit Service aee942
			{
Packit Service aee942
				/* firmware 1.00 is bogus
Packit Service aee942
				 * With a T=1 card and case 2 APDU (data from card to
Packit Service aee942
				 * host) the maximum size returned by the reader is 128
Packit Service aee942
				 * byes. The reader is then using chaining as with
Packit Service aee942
				 * extended APDU.
Packit Service aee942
				 */
Packit Service aee942
				ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
Packit Service aee942
				ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
Packit Service aee942
			}
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case ElatecTWN4_CCID_CDC:
Packit Service aee942
		case ElatecTWN4_CCID:
Packit Service aee942
		case SCM_SCL011:
Packit Service aee942
			/* restore default timeout (modified in ccid_open_hack_pre()) */
Packit Service aee942
			ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
Packit Service aee942
			break;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* Gemalto readers may report additional information */
Packit Service aee942
	if (GET_VENDOR(ccid_descriptor->readerID) == VENDOR_GEMALTO)
Packit Service aee942
		set_gemalto_firmware_features(reader_index);
Packit Service aee942
Packit Service aee942
	return return_value;
Packit Service aee942
} /* ccid_open_hack_post */
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					ccid_error
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
void ccid_error(int log_level, int error, const char *file, int line,
Packit Service aee942
	const char *function)
Packit Service aee942
{
Packit Service aee942
#ifndef NO_LOG
Packit Service aee942
	const char *text;
Packit Service aee942
	char var_text[30];
Packit Service aee942
Packit Service aee942
	switch (error)
Packit Service aee942
	{
Packit Service aee942
		case 0x00:
Packit Service aee942
			text = "Command not supported or not allowed";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0x01:
Packit Service aee942
			text = "Wrong command length";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0x05:
Packit Service aee942
			text = "Invalid slot number";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xA2:
Packit Service aee942
			text = "Card short-circuiting. Card powered off";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xA3:
Packit Service aee942
			text = "ATR too long (> 33)";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xAB:
Packit Service aee942
			text = "No data exchanged";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xB0:
Packit Service aee942
			text = "Reader in EMV mode and T=1 message too long";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xBB:
Packit Service aee942
			text = "Protocol error in EMV mode";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xBD:
Packit Service aee942
			text = "Card error during T=1 exchange";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xBE:
Packit Service aee942
			text = "Wrong APDU command length";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xE0:
Packit Service aee942
			text = "Slot busy";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xEF:
Packit Service aee942
			text = "PIN cancelled";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF0:
Packit Service aee942
			text = "PIN timeout";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF2:
Packit Service aee942
			text = "Busy with autosequence";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF3:
Packit Service aee942
			text = "Deactivated protocol";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF4:
Packit Service aee942
			text = "Procedure byte conflict";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF5:
Packit Service aee942
			text = "Class not supported";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF6:
Packit Service aee942
			text = "Protocol not supported";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF7:
Packit Service aee942
			text = "Invalid ATR checksum byte (TCK)";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xF8:
Packit Service aee942
			text = "Invalid ATR first byte";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xFB:
Packit Service aee942
			text = "Hardware error";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xFC:
Packit Service aee942
			text = "Overrun error";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xFD:
Packit Service aee942
			text = "Parity error during exchange";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xFE:
Packit Service aee942
			text = "Card absent or mute";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0xFF:
Packit Service aee942
			text = "Activity aborted by Host";
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		default:
Packit Service aee942
			if ((error >= 1) && (error <= 127))
Packit Service aee942
				(void)snprintf(var_text, sizeof(var_text), "error on byte %d",
Packit Service aee942
					error);
Packit Service aee942
			else
Packit Service aee942
				(void)snprintf(var_text, sizeof(var_text),
Packit Service aee942
					"Unknown CCID error: 0x%02X", error);
Packit Service aee942
Packit Service aee942
			text = var_text;
Packit Service aee942
			break;
Packit Service aee942
	}
Packit Service aee942
	log_msg(log_level, "%s:%d:%s %s", file, line, function, text);
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
} /* ccid_error */
Packit Service aee942