Blame examples/scardcontrol.c

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