pcsc-lite  1.8.20
formaticc.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
3  *
4  * Copyright (C) 2000-2002
5  * David Corcoran <corcoran@musclecard.com>
6  * Copyright (C) 2002-2009
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13 1. Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in the
17  documentation and/or other materials provided with the distribution.
18 3. The name of the author may not be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #ifdef __APPLE__
43 #include <PCSC/winscard.h>
44 #include <PCSC/wintypes.h>
45 #else
46 #include <wintypes.h>
47 #include <winscard.h>
48 #endif
49 
50 #ifndef MAXHOSTNAMELEN
51 #define MAXHOSTNAMELEN 64
52 #endif
53 
54 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
55 {
56  SCARDHANDLE hCard;
57  SCARDCONTEXT hContext;
58  SCARD_IO_REQUEST sRecvPci;
59  SCARD_READERSTATE rgReaderStates[1];
60  DWORD dwSendLength, dwRecvLength, dwPref, dwReaders;
61  LPSTR mszReaders = NULL;
62  BYTE s[MAX_BUFFER_SIZE], r[MAX_BUFFER_SIZE];
63  LPCSTR mszGroups;
64  LONG rv;
65  FILE *fp;
66  FILE *fo;
67  int i, p, iReader, cnum, iProtocol;
68  int iList[16];
69  char pcHost[MAXHOSTNAMELEN];
70  char pcAFile[FILENAME_MAX];
71  char pcOFile[FILENAME_MAX];
72  char line[80];
73  char *line_ptr;
74  unsigned int x;
75 
76  printf("\nWinscard PC/SC Lite Test Program\n\n");
77 
78  printf("Please enter the desired host (localhost for this machine) [localhost]: ");
79  (void)fgets(line, sizeof(line), stdin);
80  if (line[0] == '\n')
81  strncpy(pcHost, "localhost", sizeof(pcHost)-1);
82  else
83  strncpy(pcHost, line, sizeof(pcHost)-1);
84 
85  printf("Please input the desired transmit protocol (0/1) [0]: ");
86  (void)fgets(line, sizeof(line), stdin);
87  if (line[0] == '\n')
88  iProtocol = 0;
89  else
90  (void)sscanf(line, "%d", &iProtocol);
91 
92  printf("Please input the desired input apdu file: ");
93  (void)fgets(line, sizeof(line), stdin);
94  (void)sscanf(line, "%s", pcAFile);
95 
96  printf("Please input the desired output apdu file: ");
97  (void)fgets(line, sizeof(line), stdin);
98  (void)sscanf(line, "%s", pcOFile);
99 
100  fp = fopen(pcAFile, "r");
101  if (fp == NULL)
102  {
103  perror(pcAFile);
104  return 1;
105  }
106 
107  fo = fopen(pcOFile, "w");
108  if (fo == NULL)
109  {
110  perror(pcOFile);
111  (int)fclose(fp);
112  return 1;
113  }
114 
115  rv = SCardEstablishContext(SCARD_SCOPE_USER, pcHost, NULL, &hContext);
116 
117  if (rv != SCARD_S_SUCCESS)
118  {
119  printf("ERROR :: Cannot Connect to Resource Manager\n");
120  (int)fclose(fp);
121  (int)fclose(fo);
122  return 1;
123  }
124 
125  mszGroups = NULL;
126  rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);
127  if (rv != SCARD_S_SUCCESS)
128  {
129  printf("SCardListReaders error line %d: %08X\n", __LINE__, rv);
130  goto releasecontext;
131  }
132  mszReaders = malloc(sizeof(char) * dwReaders);
133  rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
134  if (rv != SCARD_S_SUCCESS)
135  {
136  printf("SCardListReaders error line %d: %08X\n", __LINE__, rv);
137  goto releasecontext;
138  }
139 
140  /*
141  * Have to understand the multi-string here
142  */
143  p = 0;
144  for (i = 0; i < dwReaders - 1; i++)
145  {
146  ++p;
147  printf("Reader %02d: %s\n", p, &mszReaders[i]);
148  iList[p] = i;
149  while (mszReaders[++i] != 0) ;
150  }
151 
152  do
153  {
154  printf("Enter the desired reader number: ");
155  (void)fgets(line, sizeof(line), stdin);
156  (void)sscanf(line, "%d", &iReader);
157  printf("\n");
158 
159  if (iReader > p || iReader <= 0)
160  {
161  printf("Invalid Value - try again\n");
162  }
163  }
164  while (iReader > p || iReader <= 0);
165 
166  rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
167  rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
168 
169  printf("Please insert a smart card\n");
170  rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
171  if (rv != SCARD_S_SUCCESS)
172  {
173  printf("SCardGetStatusChange error line %d: %08X\n", __LINE__, rv);
174  goto releasecontext;
175  }
176 
177  rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
179  &hCard, &dwPref);
180  if (rv != SCARD_S_SUCCESS)
181  {
182  printf("SCardConnect error line %d: %08X\n", __LINE__, rv);
183  goto releasecontext;
184  }
185 
186  /*
187  * Now lets get some work done
188  */
189 
190  rv = SCardBeginTransaction(hCard);
191  if (rv != SCARD_S_SUCCESS)
192  {
193  printf("SCardBeginTransaction error line %d: %08X\n", __LINE__, rv);
194  goto disconnect;
195  }
196 
197  cnum = 0;
198 
199  do
200  {
201  cnum += 1;
202 
203  if (fgets(line, sizeof(line), fp) == NULL)
204  break;
205 
206  /* comments */
207  if ('#' == line[0])
208  {
209  printf("%s", line);
210  continue;
211  }
212 
213  line_ptr = line;
214  if (sscanf(line_ptr, "%x", &x) == 0)
215  break;
216  dwSendLength = x;
217 
218  line_ptr = strchr(line_ptr, ' ');
219  if (line_ptr == NULL)
220  break;
221  line_ptr++;
222 
223  for (i = 0; i < dwSendLength; i++)
224  {
225  if (sscanf(line_ptr, "%x", &x) == 0)
226  {
227  printf("Corrupt APDU: %s\n", line);
228  goto disconnect;
229  return 1;
230  }
231  s[i] = x;
232 
233  line_ptr = strchr(line_ptr, ' ');
234 
235  if (line_ptr == NULL)
236  break;
237 
238  line_ptr++;
239  }
240 
241  printf("Processing Command %03d of length %03lX: ", cnum,
242  dwSendLength);
243  for (i=0; i<dwSendLength; i++)
244  printf("%02X ", s[i]);
245  printf("\n");
246 
247  memset(r, 0x00, MAX_BUFFER_SIZE);
248  dwRecvLength = MAX_BUFFER_SIZE;
249 
250  if (iProtocol == 0)
251  {
252  rv = SCardTransmit(hCard, SCARD_PCI_T0, s, dwSendLength,
253  &sRecvPci, r, &dwRecvLength);
254  }
255  else
256  {
257  if (iProtocol == 1)
258  {
259  rv = SCardTransmit(hCard, SCARD_PCI_T1, s, dwSendLength,
260  &sRecvPci, r, &dwRecvLength);
261  }
262  else
263  {
264  printf("Invalid Protocol\n");
265  goto endtransaction;
266  }
267  }
268 
269  if (rv != SCARD_S_SUCCESS)
270  {
271  fprintf(fo, ".error 0x%08lX\n", rv);
272  printf("Error: 0x%08lX\n", rv);
273  }
274  else
275  {
276  fprintf(fo, "%02ld ", dwRecvLength);
277  printf("Received %ld bytes: ", dwRecvLength);
278 
279  for (i = 0; i < dwRecvLength; i++)
280  {
281  fprintf(fo, "%02X ", r[i]);
282  printf("%02X ", r[i]);
283  }
284 
285  fprintf(fo, "\n");
286  printf("\n");
287  }
288 
289  if (rv == SCARD_W_RESET_CARD)
290  {
293  SCARD_RESET_CARD, &dwPref);
294  if (rv != SCARD_S_SUCCESS)
295  {
296  printf("SCardReconnect error line %d: %08X\n", __LINE__, rv);
297  goto endtransaction;
298  }
299  }
300 
301  }
302  while (1);
303 
304 endtransaction:
306 disconnect:
307  (void)SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
308 releasecontext:
309  (void)SCardReleaseContext(hContext);
310  free(mszReaders);
311 
312  (int)fclose(fp);
313  (int)fclose(fo);
314 
315  return 0;
316 }
PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
#define SCARD_SCOPE_USER
Scope in user space.
Definition: pcsclite.h:234
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition: pcsclite.h:297
#define SCARD_STATE_EMPTY
Card removed.
Definition: pcsclite.h:270
PCSC_API LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
Definition: winscard.c:195
#define SCARD_LEAVE_CARD
Do nothing on close.
Definition: pcsclite.h:252
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:242
PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes...
#define SCARD_PCI_T0
protocol control information (PCI) for T=0
Definition: pcsclite.h:95
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
Definition: winscard.c:826
#define INFINITE
Infinite timeout.
Definition: pcsclite.h:279
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:52
#define SCARD_SHARE_SHARED
Shared mode only.
Definition: pcsclite.h:249
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
Definition: pcsclite.h:216
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:241
PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
Definition: winscard.c:525
#define SCARD_PCI_T1
protocol control information (PCI) for T=1
Definition: pcsclite.h:96
#define SCARD_UNPOWER_CARD
Power down on close.
Definition: pcsclite.h:254
PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
Definition: winscard.c:234
#define SCARD_RESET_CARD
Reset on close.
Definition: pcsclite.h:253
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
This keeps a list of Windows(R) types.
PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
Definition: winscard.c:1045
Protocol Control Information (PCI)
Definition: pcsclite.h:79
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
Definition: winscard.c:1087
PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Sends an APDU to the smart card contained in the reader connected to by SCardConnect().
Definition: winscard.c:1489
This handles smart card reader communications.
PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
Definition: winscard.c:220