Blame src/ccid.c

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