Blame examples/scardcontrol.c

Packit Service aee942
/*
Packit Service aee942
    scardcontrol.c: sample code to use/test SCardControl() API
Packit Service aee942
    Copyright (C) 2004-2011   Ludovic Rousseau
Packit Service aee942
Packit Service aee942
    This program is free software; you can redistribute it and/or modify
Packit Service aee942
    it under the terms of the GNU General Public License as published by
Packit Service aee942
    the Free Software Foundation; either version 2 of the License, or
Packit Service aee942
    (at your option) any later version.
Packit Service aee942
Packit Service aee942
    This program 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
Packit Service aee942
    GNU General Public License for more details.
Packit Service aee942
Packit Service aee942
	You should have received a copy of the GNU General Public License along
Packit Service aee942
	with this program; if not, write to the Free Software Foundation, Inc., 51
Packit Service aee942
	Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service aee942
*/
Packit Service aee942
Packit Service aee942
#include <stdio.h>
Packit Service aee942
#include <stdlib.h>
Packit Service aee942
#include <sys/time.h>
Packit Service aee942
#include <unistd.h>
Packit Service aee942
#include <string.h>
Packit Service aee942
#include <arpa/inet.h>
Packit Service aee942
#ifdef __APPLE__
Packit Service aee942
#include <PCSC/winscard.h>
Packit Service aee942
#include <PCSC/wintypes.h>
Packit Service aee942
#else
Packit Service aee942
#include <winscard.h>
Packit Service aee942
#endif
Packit Service aee942
#include <reader.h>
Packit Service aee942
Packit Service aee942
#include "PCSCv2part10.h"
Packit Service aee942
Packit Service aee942
#define VERIFY_PIN
Packit Service aee942
#undef MODIFY_PIN
Packit Service aee942
#undef GET_GEMPC_FIRMWARE
Packit Service aee942
Packit Service aee942
#ifndef TRUE
Packit Service aee942
#define TRUE 1
Packit Service aee942
#define FALSE 0
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
#define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE     SCARD_CTL_CODE(1)
Packit Service aee942
Packit Service aee942
#define BLUE "\33[34m"
Packit Service aee942
#define RED "\33[31m"
Packit Service aee942
#define BRIGHT_RED "\33[01;31m"
Packit Service aee942
#define GREEN "\33[32m"
Packit Service aee942
#define NORMAL "\33[0m"
Packit Service aee942
#define MAGENTA "\33[35m"
Packit Service aee942
Packit Service aee942
/* DWORD printf(3) format */
Packit Service aee942
#ifdef __APPLE__
Packit Service aee942
/* Apple defines DWORD as uint32_t so %d is correct */
Packit Service aee942
#define LF
Packit Service aee942
#else
Packit Service aee942
/* pcsc-lite defines DWORD as unsigned long so %ld is correct */
Packit Service aee942
#define LF "l"
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
/* PCSC error message pretty print */
Packit Service aee942
#define PCSC_ERROR_EXIT(rv, text) \
Packit Service aee942
if (rv != SCARD_S_SUCCESS) \
Packit Service aee942
{ \
Packit Service aee942
	printf(text ": " RED "%s (0x%"LF"X)\n" NORMAL, pcsc_stringify_error(rv), rv); \
Packit Service aee942
	goto end; \
Packit Service aee942
} \
Packit Service aee942
else \
Packit Service aee942
	printf(text ": " BLUE "OK\n\n" NORMAL);
Packit Service aee942
Packit Service aee942
#define PCSC_ERROR_CONT(rv, text) \
Packit Service aee942
if (rv != SCARD_S_SUCCESS) \
Packit Service aee942
	printf(text ": " BLUE "%s (0x%"LF"X)\n" NORMAL, pcsc_stringify_error(rv), rv); \
Packit Service aee942
else \
Packit Service aee942
	printf(text ": " BLUE "OK\n\n" NORMAL);
Packit Service aee942
Packit Service aee942
#define PRINT_GREEN(text, value) \
Packit Service aee942
	printf("%s: " GREEN "%s\n" NORMAL, text, value)
Packit Service aee942
Packit Service aee942
#define PRINT_GREEN_DEC(text, value) \
Packit Service aee942
	printf("%s: " GREEN "%d\n" NORMAL, text, value)
Packit Service aee942
Packit Service aee942
#define PRINT_RED_DEC(text, value) \
Packit Service aee942
	printf("%s: " RED "%d\n" NORMAL, text, value)
Packit Service aee942
Packit Service aee942
#define PRINT_GREEN_HEX2(text, value) \
Packit Service aee942
	printf("%s: " GREEN "0x%02X\n" NORMAL, text, value)
Packit Service aee942
Packit Service aee942
#define PRINT_GREEN_HEX4(text, value) \
Packit Service aee942
	printf("%s: " GREEN "0x%04X\n" NORMAL, text, value)
Packit Service aee942
Packit Service aee942
static void parse_properties(unsigned char *bRecvBuffer, int length)
Packit Service aee942
{
Packit Service aee942
	unsigned char *p;
Packit Service aee942
	int i;
Packit Service aee942
Packit Service aee942
	p = bRecvBuffer;
Packit Service aee942
	while (p-bRecvBuffer < length)
Packit Service aee942
	{
Packit Service aee942
		int tag, len, value;
Packit Service aee942
Packit Service aee942
		tag = *p++;
Packit Service aee942
		len = *p++;
Packit Service aee942
Packit Service aee942
		switch(len)
Packit Service aee942
		{
Packit Service aee942
			case 1:
Packit Service aee942
				value = *p;
Packit Service aee942
				break;
Packit Service aee942
			case 2:
Packit Service aee942
				value = *p + (*(p+1)<<8);
Packit Service aee942
				break;
Packit Service aee942
			case 4:
Packit Service aee942
				value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24);
Packit Service aee942
				break;
Packit Service aee942
			default:
Packit Service aee942
				value = -1;
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		switch(tag)
Packit Service aee942
		{
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_wLcdLayout:
Packit Service aee942
				PRINT_GREEN_HEX4(" wLcdLayout", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_bEntryValidationCondition:
Packit Service aee942
				PRINT_GREEN_HEX2(" bEntryValidationCondition", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_bTimeOut2:
Packit Service aee942
				PRINT_GREEN_HEX2(" bTimeOut2", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_wLcdMaxCharacters:
Packit Service aee942
				PRINT_GREEN_HEX4(" wLcdMaxCharacters", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_wLcdMaxLines:
Packit Service aee942
				PRINT_GREEN_HEX4(" wLcdMaxLines", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_bMinPINSize:
Packit Service aee942
				PRINT_GREEN_HEX2(" bMinPINSize", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_bMaxPINSize:
Packit Service aee942
				PRINT_GREEN_HEX2(" bMaxPINSize", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_sFirmwareID:
Packit Service aee942
				printf(" sFirmwareID: " GREEN);
Packit Service aee942
				for (i=0; i
Packit Service aee942
					putchar(p[i]);
Packit Service aee942
				printf(NORMAL "\n");
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_bPPDUSupport:
Packit Service aee942
				PRINT_GREEN_HEX2(" bPPDUSupport", value);
Packit Service aee942
				if (value & 1)
Packit Service aee942
					printf("  PPDU is supported over SCardControl using FEATURE_CCID_ESC_COMMAND\n");
Packit Service aee942
				if (value & 2)
Packit Service aee942
					printf("  PPDU is supported over SCardTransmit\n");
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize:
Packit Service aee942
				PRINT_GREEN_DEC(" dwMaxAPDUDataSize", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_wIdVendor:
Packit Service aee942
				PRINT_GREEN_HEX2(" wIdVendor", value);
Packit Service aee942
				break;
Packit Service aee942
			case PCSCv2_PART10_PROPERTY_wIdProduct:
Packit Service aee942
				PRINT_GREEN_HEX2(" wIdProduct", value);
Packit Service aee942
				break;
Packit Service aee942
			default:
Packit Service aee942
				printf(" Unknown tag: 0x%02X (length = %d)\n", tag, len);
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		p += len;
Packit Service aee942
	}
Packit Service aee942
} /* parse_properties */
Packit Service aee942
Packit Service aee942
Packit Service aee942
static const char *pinpad_return_codes(unsigned char bRecvBuffer[])
Packit Service aee942
{
Packit Service aee942
	const char * ret = "UNKNOWN";
Packit Service aee942
Packit Service aee942
	if ((0x90 == bRecvBuffer[0]) && (0x00 == bRecvBuffer[1]))
Packit Service aee942
		ret = "Success";
Packit Service aee942
Packit Service aee942
	if (0x64 == bRecvBuffer[0])
Packit Service aee942
	{
Packit Service aee942
		switch (bRecvBuffer[1])
Packit Service aee942
		{
Packit Service aee942
			case 0x00:
Packit Service aee942
				ret = "Timeout";
Packit Service aee942
				break;
Packit Service aee942
Packit Service aee942
			case 0x01:
Packit Service aee942
				ret = "Cancelled by user";
Packit Service aee942
				break;
Packit Service aee942
Packit Service aee942
			case 0x02:
Packit Service aee942
				ret = "PIN mismatch";
Packit Service aee942
				break;
Packit Service aee942
Packit Service aee942
			case 0x03:
Packit Service aee942
				ret = "Too short or too long PIN";
Packit Service aee942
				break;
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	return ret;
Packit Service aee942
}
Packit Service aee942
Packit Service aee942
int main(int argc, char *argv[])
Packit Service aee942
{
Packit Service aee942
	LONG rv;
Packit Service aee942
	SCARDCONTEXT hContext;
Packit Service aee942
	DWORD dwReaders;
Packit Service aee942
	LPSTR mszReaders = NULL;
Packit Service aee942
	char *ptr, **readers = NULL;
Packit Service aee942
	int nbReaders;
Packit Service aee942
	SCARDHANDLE hCard;
Packit Service aee942
	DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
Packit Service aee942
	BYTE pbAtr[MAX_ATR_SIZE] = "";
Packit Service aee942
	char pbReader[MAX_READERNAME] = "";
Packit Service aee942
	int reader_nb;
Packit Service aee942
	unsigned int i;
Packit Service aee942
	unsigned char bSendBuffer[MAX_BUFFER_SIZE];
Packit Service aee942
	unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
Packit Service aee942
	DWORD send_length, length;
Packit Service aee942
	DWORD verify_ioctl = 0;
Packit Service aee942
	DWORD modify_ioctl = 0;
Packit Service aee942
	DWORD pin_properties_ioctl = 0;
Packit Service aee942
	DWORD mct_readerdirect_ioctl = 0;
Packit Service aee942
	DWORD properties_in_tlv_ioctl = 0;
Packit Service aee942
	DWORD ccid_esc_command = 0;
Packit Service aee942
	SCARD_IO_REQUEST pioRecvPci;
Packit Service aee942
	SCARD_IO_REQUEST pioSendPci;
Packit Service aee942
	PCSC_TLV_STRUCTURE *pcsc_tlv;
Packit Service aee942
#if defined(VERIFY_PIN) | defined(MODIFY_PIN)
Packit Service aee942
	int offset;
Packit Service aee942
#endif
Packit Service aee942
#ifdef VERIFY_PIN
Packit Service aee942
	PIN_VERIFY_STRUCTURE *pin_verify;
Packit Service aee942
#endif
Packit Service aee942
#ifdef MODIFY_PIN
Packit Service aee942
	PIN_MODIFY_STRUCTURE *pin_modify;
Packit Service aee942
#endif
Packit Service aee942
	int PIN_min_size = 4;
Packit Service aee942
	int PIN_max_size = 8;
Packit Service aee942
Packit Service aee942
	/* table for bEntryValidationCondition
Packit Service aee942
	 * 0x01: Max size reached
Packit Service aee942
	 * 0x02: Validation key pressed
Packit Service aee942
	 * 0x04: Timeout occured
Packit Service aee942
	 */
Packit Service aee942
	int bEntryValidationCondition = 7;
Packit Service aee942
Packit Service aee942
	printf("SCardControl sample code\n");
Packit Service aee942
	printf("V 1.4 © 2004-2010, Ludovic Rousseau <ludovic.rousseau@free.fr>\n\n");
Packit Service aee942
Packit Service aee942
	printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL!\n");
Packit Service aee942
	printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);
Packit Service aee942
Packit Service aee942
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
Packit Service aee942
	if (rv != SCARD_S_SUCCESS)
Packit Service aee942
	{
Packit Service aee942
		printf("SCardEstablishContext: Cannot Connect to Resource Manager %"LF"X\n", rv);
Packit Service aee942
		return 1;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* Retrieve the available readers list */
Packit Service aee942
	rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardListReaders")
Packit Service aee942
Packit Service aee942
	mszReaders = malloc(sizeof(char)*dwReaders);
Packit Service aee942
	if (mszReaders == NULL)
Packit Service aee942
	{
Packit Service aee942
		printf("malloc: not enough memory\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
Packit Service aee942
	if (rv != SCARD_S_SUCCESS)
Packit Service aee942
		printf("SCardListReader: %"LF"X\n", rv);
Packit Service aee942
Packit Service aee942
	/* Extract readers from the null separated string and get the total
Packit Service aee942
	 * number of readers */
Packit Service aee942
	nbReaders = 0;
Packit Service aee942
	ptr = mszReaders;
Packit Service aee942
	while (*ptr != '\0')
Packit Service aee942
	{
Packit Service aee942
		ptr += strlen(ptr)+1;
Packit Service aee942
		nbReaders++;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	if (nbReaders == 0)
Packit Service aee942
	{
Packit Service aee942
		printf("No reader found\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* allocate the readers table */
Packit Service aee942
	readers = calloc(nbReaders, sizeof(char *));
Packit Service aee942
	if (NULL == readers)
Packit Service aee942
	{
Packit Service aee942
		printf("Not enough memory for readers[]\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* fill the readers table */
Packit Service aee942
	nbReaders = 0;
Packit Service aee942
	ptr = mszReaders;
Packit Service aee942
	printf("Available readers (use command line argument to select)\n");
Packit Service aee942
	while (*ptr != '\0')
Packit Service aee942
	{
Packit Service aee942
		printf("%d: %s\n", nbReaders, ptr);
Packit Service aee942
		readers[nbReaders] = ptr;
Packit Service aee942
		ptr += strlen(ptr)+1;
Packit Service aee942
		nbReaders++;
Packit Service aee942
	}
Packit Service aee942
	printf("\n");
Packit Service aee942
Packit Service aee942
	if (argc > 1)
Packit Service aee942
	{
Packit Service aee942
		reader_nb = atoi(argv[1]);
Packit Service aee942
		if (reader_nb < 0 || reader_nb >= nbReaders)
Packit Service aee942
		{
Packit Service aee942
			printf("Wrong reader index: %d\n", reader_nb);
Packit Service aee942
			goto end;
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
	else
Packit Service aee942
		reader_nb = 0;
Packit Service aee942
Packit Service aee942
	/* connect to a reader (even without a card) */
Packit Service aee942
	dwActiveProtocol = -1;
Packit Service aee942
	printf("Using reader: " GREEN "%s\n" NORMAL, readers[reader_nb]);
Packit Service aee942
	rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
Packit Service aee942
		SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
Packit Service aee942
	printf(" Protocol: " GREEN "%"LF"d\n" NORMAL, dwActiveProtocol);
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardConnect")
Packit Service aee942
Packit Service aee942
#ifdef GET_GEMPC_FIRMWARE
Packit Service aee942
	/* get GemPC firmware */
Packit Service aee942
	printf(" Get GemPC Firmware\n");
Packit Service aee942
Packit Service aee942
	/* this is specific to Gemalto readers */
Packit Service aee942
	bSendBuffer[0] = 0x02;
Packit Service aee942
	rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
Packit Service aee942
		1, bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
Packit Service aee942
	printf(" Firmware: " GREEN);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
	printf(NORMAL "\n");
Packit Service aee942
Packit Service aee942
	bRecvBuffer[length] = '\0';
Packit Service aee942
	printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);
Packit Service aee942
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardControl")
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
	/* does the reader support PIN verification? */
Packit Service aee942
	rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
Packit Service aee942
		bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardControl")
Packit Service aee942
Packit Service aee942
	printf(" TLV (%"LF"d): " GREEN, length);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
	printf(NORMAL "\n");
Packit Service aee942
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)")
Packit Service aee942
Packit Service aee942
	if (length % sizeof(PCSC_TLV_STRUCTURE))
Packit Service aee942
	{
Packit Service aee942
		printf("Inconsistent result! Bad TLV values!\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* get the number of elements instead of the complete size */
Packit Service aee942
	length /= sizeof(PCSC_TLV_STRUCTURE);
Packit Service aee942
Packit Service aee942
	pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
Packit Service aee942
	for (i = 0; i < length; i++)
Packit Service aee942
	{
Packit Service aee942
		switch (pcsc_tlv[i].tag)
Packit Service aee942
		{
Packit Service aee942
			case FEATURE_VERIFY_PIN_DIRECT:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_VERIFY_PIN_DIRECT");
Packit Service aee942
				verify_ioctl = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			case FEATURE_MODIFY_PIN_DIRECT:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_MODIFY_PIN_DIRECT");
Packit Service aee942
				modify_ioctl = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			case FEATURE_IFD_PIN_PROPERTIES:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_IFD_PIN_PROPERTIES");
Packit Service aee942
				pin_properties_ioctl = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			case FEATURE_MCT_READER_DIRECT:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_MCT_READER_DIRECT");
Packit Service aee942
				mct_readerdirect_ioctl = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			case FEATURE_GET_TLV_PROPERTIES:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_GET_TLV_PROPERTIES");
Packit Service aee942
				properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			case FEATURE_CCID_ESC_COMMAND:
Packit Service aee942
				PRINT_GREEN("Reader supports", "FEATURE_CCID_ESC_COMMAND");
Packit Service aee942
				ccid_esc_command = ntohl(pcsc_tlv[i].value);
Packit Service aee942
				break;
Packit Service aee942
			default:
Packit Service aee942
				PRINT_RED_DEC("Can't parse tag", pcsc_tlv[i].tag);
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
	printf("\n");
Packit Service aee942
Packit Service aee942
	if (properties_in_tlv_ioctl)
Packit Service aee942
	{
Packit Service aee942
		int value;
Packit Service aee942
		int ret;
Packit Service aee942
Packit Service aee942
		rv = SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0,
Packit Service aee942
			bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
		PCSC_ERROR_CONT(rv, "SCardControl(GET_TLV_PROPERTIES)")
Packit Service aee942
Packit Service aee942
		printf("GET_TLV_PROPERTIES (" GREEN "%"LF"d" NORMAL "): " GREEN, length);
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
		printf(NORMAL "\n");
Packit Service aee942
Packit Service aee942
		printf("\nDisplay all the properties:\n");
Packit Service aee942
		parse_properties(bRecvBuffer, length);
Packit Service aee942
Packit Service aee942
		printf("\nFind a specific property:\n");
Packit Service aee942
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_buffer(bRecvBuffer, length, PCSCv2_PART10_PROPERTY_wIdVendor, &value);
Packit Service aee942
		if (ret)
Packit Service aee942
			PRINT_RED_DEC(" wIdVendor", ret);
Packit Service aee942
		else
Packit Service aee942
			PRINT_GREEN_HEX4(" wIdVendor", value);
Packit Service aee942
Packit Service aee942
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_wIdProduct, &value);
Packit Service aee942
		if (ret)
Packit Service aee942
			PRINT_RED_DEC(" wIdProduct", ret);
Packit Service aee942
		else
Packit Service aee942
			PRINT_GREEN_HEX4(" wIdProduct", value);
Packit Service aee942
Packit Service aee942
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_bMinPINSize, &value);
Packit Service aee942
		if (0 == ret)
Packit Service aee942
		{
Packit Service aee942
			PIN_min_size = value;
Packit Service aee942
			PRINT_GREEN_DEC(" PIN min size defined", PIN_min_size);
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
Packit Service aee942
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_bMaxPINSize, &value);
Packit Service aee942
		if (0 == ret)
Packit Service aee942
		{
Packit Service aee942
			PIN_max_size = value;
Packit Service aee942
			PRINT_GREEN_DEC(" PIN max size defined", PIN_max_size);
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		ret = PCSCv2Part10_find_TLV_property_by_tag_from_hcard(hCard, PCSCv2_PART10_PROPERTY_bEntryValidationCondition, &value);
Packit Service aee942
		if (0 == ret)
Packit Service aee942
		{
Packit Service aee942
			bEntryValidationCondition = value;
Packit Service aee942
			PRINT_GREEN_DEC(" Entry Validation Condition defined",
Packit Service aee942
				bEntryValidationCondition);
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		printf("\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	if (mct_readerdirect_ioctl)
Packit Service aee942
	{
Packit Service aee942
		char secoder_info[] = { 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
Packit Service aee942
Packit Service aee942
		rv = SCardControl(hCard, mct_readerdirect_ioctl, secoder_info,
Packit Service aee942
			sizeof(secoder_info), bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
		PCSC_ERROR_CONT(rv, "SCardControl(MCT_READER_DIRECT)")
Packit Service aee942
Packit Service aee942
		printf("MCT_READER_DIRECT (%"LF"d): ", length);
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
		printf("\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	if (pin_properties_ioctl)
Packit Service aee942
	{
Packit Service aee942
		PIN_PROPERTIES_STRUCTURE *pin_properties;
Packit Service aee942
Packit Service aee942
		rv = SCardControl(hCard, pin_properties_ioctl, NULL, 0,
Packit Service aee942
			bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
		PCSC_ERROR_CONT(rv, "SCardControl(pin_properties_ioctl)")
Packit Service aee942
Packit Service aee942
		printf("PIN PROPERTIES (" GREEN "%"LF"d" NORMAL "): " GREEN, length);
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
		printf(NORMAL "\n");
Packit Service aee942
Packit Service aee942
		pin_properties = (PIN_PROPERTIES_STRUCTURE *)bRecvBuffer;
Packit Service aee942
		bEntryValidationCondition = pin_properties ->	bEntryValidationCondition;
Packit Service aee942
		PRINT_GREEN_HEX4(" wLcdLayout", pin_properties -> wLcdLayout);
Packit Service aee942
		PRINT_GREEN_DEC(" bEntryValidationCondition", bEntryValidationCondition);
Packit Service aee942
		PRINT_GREEN_DEC(" bTimeOut2", pin_properties -> bTimeOut2);
Packit Service aee942
Packit Service aee942
		printf("\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
#ifdef GET_GEMPC_FIRMWARE
Packit Service aee942
	if (ccid_esc_command)
Packit Service aee942
	{
Packit Service aee942
		/* get GemPC firmware */
Packit Service aee942
		printf("Get GemPC Firmware\n");
Packit Service aee942
Packit Service aee942
		/* this is specific to Gemalto readers */
Packit Service aee942
		bSendBuffer[0] = 0x02;
Packit Service aee942
		rv = SCardControl(hCard, ccid_esc_command, bSendBuffer,
Packit Service aee942
			1, bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
Packit Service aee942
		printf(" Firmware: " GREEN);
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf("%02X ", bRecvBuffer[i]);
Packit Service aee942
		printf(NORMAL "\n");
Packit Service aee942
Packit Service aee942
		bRecvBuffer[length] = '\0';
Packit Service aee942
		printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);
Packit Service aee942
Packit Service aee942
		PCSC_ERROR_CONT(rv, "SCardControl")
Packit Service aee942
	}
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
	if (0 == verify_ioctl)
Packit Service aee942
	{
Packit Service aee942
		printf("Reader %s does not support PIN verification\n",
Packit Service aee942
			readers[reader_nb]);
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* get card status */
Packit Service aee942
	dwAtrLen = sizeof(pbAtr);
Packit Service aee942
	dwReaderLen = sizeof(pbReader);
Packit Service aee942
	rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
Packit Service aee942
		pbAtr, &dwAtrLen);
Packit Service aee942
	printf(" Reader: %s (length %"LF"d bytes)\n", pbReader, dwReaderLen);
Packit Service aee942
	printf(" State: 0x%04"LF"X\n", dwState);
Packit Service aee942
	printf(" Prot: %"LF"d\n", dwProt);
Packit Service aee942
	printf(" ATR (length %"LF"d bytes):", dwAtrLen);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", pbAtr[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardStatus")
Packit Service aee942
Packit Service aee942
	if (dwState & SCARD_ABSENT)
Packit Service aee942
	{
Packit Service aee942
		printf("No card inserted\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* re-connect to a reader (with a card) */
Packit Service aee942
	dwActiveProtocol = -1;
Packit Service aee942
	rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
Packit Service aee942
		SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
Packit Service aee942
		&dwActiveProtocol);
Packit Service aee942
	printf(" Protocol: %"LF"d\n", dwActiveProtocol);
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardReconnect")
Packit Service aee942
Packit Service aee942
	switch(dwActiveProtocol)
Packit Service aee942
	{
Packit Service aee942
		case SCARD_PROTOCOL_T0:
Packit Service aee942
			pioSendPci = *SCARD_PCI_T0;
Packit Service aee942
			break;
Packit Service aee942
		case SCARD_PROTOCOL_T1:
Packit Service aee942
			pioSendPci = *SCARD_PCI_T1;
Packit Service aee942
			break;
Packit Service aee942
		default:
Packit Service aee942
			printf("Unknown protocol. No card present?\n");
Packit Service aee942
			return -1;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* APDU select applet */
Packit Service aee942
	printf("Select applet: ");
Packit Service aee942
	send_length = 11;
Packit Service aee942
	memcpy(bSendBuffer, "\x00\xA4\x04\x00\x06\xA0\x00\x00\x00\x18\xFF",
Packit Service aee942
		send_length);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bSendBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	length = sizeof(bRecvBuffer);
Packit Service aee942
	rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
Packit Service aee942
		&pioRecvPci, bRecvBuffer, &length);
Packit Service aee942
	printf(" card response:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardTransmit")
Packit Service aee942
	if ((bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00))
Packit Service aee942
	{
Packit Service aee942
		printf("Error: test applet not found!\n");
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
#ifdef VERIFY_PIN
Packit Service aee942
	/* verify PIN */
Packit Service aee942
	printf(" Secure verify PIN\n");
Packit Service aee942
	pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;
Packit Service aee942
Packit Service aee942
	/* PC/SC v2.02.05 Part 10 PIN verification data structure */
Packit Service aee942
	pin_verify -> bTimerOut = 0x00;
Packit Service aee942
	pin_verify -> bTimerOut2 = 0x00;
Packit Service aee942
	pin_verify -> bmFormatString = 0x82;
Packit Service aee942
	pin_verify -> bmPINBlockString = 0x08;
Packit Service aee942
	pin_verify -> bmPINLengthFormat = 0x00;
Packit Service aee942
	pin_verify -> wPINMaxExtraDigit = (PIN_min_size << 8) + PIN_max_size;
Packit Service aee942
	pin_verify -> bEntryValidationCondition = bEntryValidationCondition;
Packit Service aee942
	pin_verify -> bNumberMessage = 0x01;
Packit Service aee942
	pin_verify -> wLangId = 0x0904;
Packit Service aee942
	pin_verify -> bMsgIndex = 0x00;
Packit Service aee942
	pin_verify -> bTeoPrologue[0] = 0x00;
Packit Service aee942
	pin_verify -> bTeoPrologue[1] = 0x00;
Packit Service aee942
	pin_verify -> bTeoPrologue[2] = 0x00;
Packit Service aee942
	/* pin_verify -> ulDataLength = 0x00; we don't know the size yet */
Packit Service aee942
Packit Service aee942
	/* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
Packit Service aee942
	offset = 0;
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* CLA */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x20;	/* INS: VERIFY */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* P1 */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* P2 */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x08;	/* Lc: 8 data bytes */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
Packit Service aee942
	pin_verify -> abData[offset++] = 0x00;	/* '\0' */
Packit Service aee942
	pin_verify -> ulDataLength = offset;	/* APDU size */
Packit Service aee942
Packit Service aee942
	length = sizeof(PIN_VERIFY_STRUCTURE) + offset;
Packit Service aee942
Packit Service aee942
	printf(" command:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bSendBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	printf("Enter your PIN: ");
Packit Service aee942
	fflush(stdout);
Packit Service aee942
	memset(bRecvBuffer, 0xAA, sizeof bRecvBuffer);
Packit Service aee942
	rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
Packit Service aee942
		length, bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
Packit Service aee942
	{
Packit Service aee942
#ifndef S_SPLINT_S
Packit Service aee942
		fd_set fd;
Packit Service aee942
#endif
Packit Service aee942
		struct timeval timeout;
Packit Service aee942
Packit Service aee942
		FD_ZERO(&fd;;
Packit Service aee942
		FD_SET(STDIN_FILENO, &fd;;	/* stdin */
Packit Service aee942
		timeout.tv_sec = 0;			/* timeout = 0.1s */
Packit Service aee942
		timeout.tv_usec = 100000;
Packit Service aee942
Packit Service aee942
		/* we only try to read stdin if the pinpad is on a keyboard
Packit Service aee942
		 * we do not read stdin for a SPR 532 for example */
Packit Service aee942
		if (select(1, &fd, NULL, NULL, &timeout) > 0)
Packit Service aee942
		{
Packit Service aee942
			/* read the fake digits */
Packit Service aee942
			char in[40];	/* 4 digits + \n + \0 */
Packit Service aee942
			char *s = fgets(in, sizeof(in), stdin);
Packit Service aee942
Packit Service aee942
			if (s)
Packit Service aee942
				printf("keyboard sent: %s", in);
Packit Service aee942
		}
Packit Service aee942
		else
Packit Service aee942
			/* if it is not a keyboard */
Packit Service aee942
			printf("\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	printf(" card response:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
	printf(": %s\n", pinpad_return_codes(bRecvBuffer));
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardControl")
Packit Service aee942
Packit Service aee942
	/* verify PIN dump */
Packit Service aee942
	printf("\nverify PIN dump: ");
Packit Service aee942
	send_length = 5;
Packit Service aee942
	memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
Packit Service aee942
		send_length);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bSendBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	length = sizeof(bRecvBuffer);
Packit Service aee942
	rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
Packit Service aee942
		&pioRecvPci, bRecvBuffer, &length);
Packit Service aee942
	printf(" card response:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardTransmit")
Packit Service aee942
Packit Service aee942
	if ((2 == length) && (0x6C == bRecvBuffer[0]))
Packit Service aee942
	{
Packit Service aee942
		printf("\nverify PIN dump: ");
Packit Service aee942
		send_length = 5;
Packit Service aee942
		memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
Packit Service aee942
			send_length);
Packit Service aee942
		bSendBuffer[4] = bRecvBuffer[1];
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf(" %02X", bSendBuffer[i]);
Packit Service aee942
		printf("\n");
Packit Service aee942
		length = sizeof(bRecvBuffer);
Packit Service aee942
		rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
Packit Service aee942
			&pioRecvPci, bRecvBuffer, &length);
Packit Service aee942
		printf(" card response:");
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
		printf("\n");
Packit Service aee942
		PCSC_ERROR_EXIT(rv, "SCardTransmit")
Packit Service aee942
	}
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
	/* check if the reader supports Modify PIN */
Packit Service aee942
	if (0 == modify_ioctl)
Packit Service aee942
	{
Packit Service aee942
		printf("Reader %s does not support PIN modification\n",
Packit Service aee942
			readers[reader_nb]);
Packit Service aee942
		goto end;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
#ifdef MODIFY_PIN
Packit Service aee942
	/* Modify PIN */
Packit Service aee942
	printf(" Secure modify PIN\n");
Packit Service aee942
	pin_modify = (PIN_MODIFY_STRUCTURE *)bSendBuffer;
Packit Service aee942
Packit Service aee942
	/* Table for bConfirmPIN and bNumberMessage
Packit Service aee942
	 * bConfirmPIN = 3, bNumberMessage = 3: "Enter Pin" "New Pin" "Confirm Pin"
Packit Service aee942
	 * bConfirmPIN = 2, bNumberMessage = 2: "Enter Pin" "New Pin"
Packit Service aee942
	 * bConfirmPIN = 1, bNumberMessage = 2: "New Pin" "Confirm Pin"
Packit Service aee942
	 * bConfirmPIN = 0, bNumberMessage = 1: "New Pin"
Packit Service aee942
	 */
Packit Service aee942
	/* table for bMsgIndex[1-3]
Packit Service aee942
	 * 00: PIN insertion prompt        “ENTER SMARTCARD PIN”
Packit Service aee942
	 * 01: PIN Modification prompt     “ ENTER NEW PIN”
Packit Service aee942
	 * 02: NEW PIN Confirmation prompt “ CONFIRM NEW PIN”
Packit Service aee942
	 */
Packit Service aee942
	/* PC/SC v2.02.05 Part 10 PIN modification data structure */
Packit Service aee942
	pin_modify -> bTimerOut = 0x00;
Packit Service aee942
	pin_modify -> bTimerOut2 = 0x00;
Packit Service aee942
	pin_modify -> bmFormatString = 0x82;
Packit Service aee942
	pin_modify -> bmPINBlockString = 0x04;
Packit Service aee942
	pin_modify -> bmPINLengthFormat = 0x00;
Packit Service aee942
	pin_modify -> bInsertionOffsetOld = 0x00;	/* offset from APDU start */
Packit Service aee942
	pin_modify -> bInsertionOffsetNew = 0x04;	/* offset from APDU start */
Packit Service aee942
	pin_modify -> wPINMaxExtraDigit = (PIN_min_size << 8) + PIN_max_size;
Packit Service aee942
	pin_modify -> bConfirmPIN = 0x03;	/* b0 set = confirmation requested */
Packit Service aee942
									/* b1 set = current PIN entry requested */
Packit Service aee942
	pin_modify -> bEntryValidationCondition = bEntryValidationCondition;
Packit Service aee942
	pin_modify -> bNumberMessage = 0x03; /* see table above */
Packit Service aee942
	pin_modify -> wLangId = 0x0904;
Packit Service aee942
	pin_modify -> bMsgIndex1 = 0x00;
Packit Service aee942
	pin_modify -> bMsgIndex2 = 0x01;
Packit Service aee942
	pin_modify -> bMsgIndex3 = 0x02;
Packit Service aee942
	pin_modify -> bTeoPrologue[0] = 0x00;
Packit Service aee942
	pin_modify -> bTeoPrologue[1] = 0x00;
Packit Service aee942
	pin_modify -> bTeoPrologue[2] = 0x00;
Packit Service aee942
	/* pin_modify -> ulDataLength = 0x00; we don't know the size yet */
Packit Service aee942
Packit Service aee942
	/* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
Packit Service aee942
	offset = 0;
Packit Service aee942
	pin_modify -> abData[offset++] = 0x00;	/* CLA */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x24;	/* INS: CHANGE/UNBLOCK */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x00;	/* P1 */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x00;	/* P2 */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x08;	/* Lc: 2x8 data bytes */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' old PIN */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' new PIN */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> abData[offset++] = 0x30;	/* '0' */
Packit Service aee942
	pin_modify -> ulDataLength = offset;	/* APDU size */
Packit Service aee942
Packit Service aee942
	length = sizeof(PIN_MODIFY_STRUCTURE) + offset;
Packit Service aee942
Packit Service aee942
	printf(" command:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bSendBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	printf("Enter your PIN: ");
Packit Service aee942
	fflush(stdout);
Packit Service aee942
	memset(bRecvBuffer, 0xAA, sizeof bRecvBuffer);
Packit Service aee942
	rv = SCardControl(hCard, modify_ioctl, bSendBuffer,
Packit Service aee942
		length, bRecvBuffer, sizeof(bRecvBuffer), &length);
Packit Service aee942
Packit Service aee942
	{
Packit Service aee942
#ifndef S_SPLINT_S
Packit Service aee942
		fd_set fd;
Packit Service aee942
#endif
Packit Service aee942
		struct timeval timeout;
Packit Service aee942
Packit Service aee942
		/* old PIN, new PIN, confirmation PIN */
Packit Service aee942
		/* if the command is aborted we will not read every "PIN" */
Packit Service aee942
		for (i=0; i<3; i++)
Packit Service aee942
		{
Packit Service aee942
			FD_ZERO(&fd;;
Packit Service aee942
			FD_SET(STDIN_FILENO, &fd;;	/* stdin */
Packit Service aee942
			timeout.tv_sec = 0;			/* timeout = 0.1s */
Packit Service aee942
			timeout.tv_usec = 100000;
Packit Service aee942
Packit Service aee942
			/* we only try to read stdin if the pinpad is on a keyboard
Packit Service aee942
			 * we do not read stdin for a SPR 532 for example */
Packit Service aee942
			if (select(1, &fd, NULL, NULL, &timeout) > 0)
Packit Service aee942
			{
Packit Service aee942
				/* read the fake digits */
Packit Service aee942
				char in[40];	/* 4 digits + \n + \0 */
Packit Service aee942
				char *ret;
Packit Service aee942
Packit Service aee942
				ret = fgets(in, sizeof(in), stdin);
Packit Service aee942
				if (ret)
Packit Service aee942
					printf("keyboard sent: %s", in);
Packit Service aee942
			}
Packit Service aee942
			else
Packit Service aee942
			{
Packit Service aee942
				/* if it is not a keyboard */
Packit Service aee942
				printf("\n");
Packit Service aee942
Packit Service aee942
				/* exit the for() loop */
Packit Service aee942
				break;
Packit Service aee942
			}
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	printf(" card response:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardControl")
Packit Service aee942
Packit Service aee942
	/* modify PIN dump */
Packit Service aee942
	printf("\nmodify PIN dump: ");
Packit Service aee942
	send_length = 5;
Packit Service aee942
	memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
Packit Service aee942
		send_length);
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bSendBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	length = sizeof(bRecvBuffer);
Packit Service aee942
	rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
Packit Service aee942
		&pioRecvPci, bRecvBuffer, &length);
Packit Service aee942
	printf(" card response:");
Packit Service aee942
	for (i=0; i
Packit Service aee942
		printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
	printf("\n");
Packit Service aee942
	PCSC_ERROR_EXIT(rv, "SCardTransmit")
Packit Service aee942
Packit Service aee942
	if ((2 == length) && (0x6C == bRecvBuffer[0]))
Packit Service aee942
	{
Packit Service aee942
		printf("\nverify PIN dump: ");
Packit Service aee942
		send_length = 5;
Packit Service aee942
		memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
Packit Service aee942
			send_length);
Packit Service aee942
		bSendBuffer[4] = bRecvBuffer[1];
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf(" %02X", bSendBuffer[i]);
Packit Service aee942
		printf("\n");
Packit Service aee942
		length = sizeof(bRecvBuffer);
Packit Service aee942
		rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
Packit Service aee942
			&pioRecvPci, bRecvBuffer, &length);
Packit Service aee942
		printf(" card response:");
Packit Service aee942
		for (i=0; i
Packit Service aee942
			printf(" %02X", bRecvBuffer[i]);
Packit Service aee942
		printf("\n");
Packit Service aee942
		PCSC_ERROR_EXIT(rv, "SCardTransmit")
Packit Service aee942
	}
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
	/* card disconnect */
Packit Service aee942
	rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
Packit Service aee942
	PCSC_ERROR_CONT(rv, "SCardDisconnect")
Packit Service aee942
Packit Service aee942
end:
Packit Service aee942
	/* We try to leave things as clean as possible */
Packit Service aee942
	rv = SCardReleaseContext(hContext);
Packit Service aee942
	if (rv != SCARD_S_SUCCESS)
Packit Service aee942
		printf("SCardReleaseContext: %s (0x%"LF"X)\n", pcsc_stringify_error(rv),
Packit Service aee942
			rv);
Packit Service aee942
Packit Service aee942
	/* free allocated memory */
Packit Service aee942
	if (mszReaders)
Packit Service aee942
		free(mszReaders);
Packit Service aee942
	if (readers)
Packit Service aee942
		free(readers);
Packit Service aee942
Packit Service aee942
	return 0;
Packit Service aee942
} /* main */
Packit Service aee942