/[pcsclite]/trunk/Drivers/ccid/examples/scardcontrol.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/examples/scardcontrol.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1290 - (hide annotations) (download)
Wed Oct 20 13:57:38 2004 UTC (8 years, 7 months ago) by rousseau
File MIME type: text/plain
File size: 9327 byte(s)
set wPINMaxExtraDigit: set max to 8 (instead of 4) to differentiate it
from min (set to 4)
1 rousseau 889 /*
2     scardcontrol.c: sample code to use/test SCardControl() API
3     Copyright (C) 2004 Ludovic Rousseau
4    
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18     */
19    
20     /*
21     * $Id$
22     */
23    
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <time.h>
27     #include <unistd.h>
28     #include <string.h>
29 rousseau 972 #include <PCSC/winscard.h>
30 rousseau 889
31     #ifndef TRUE
32     #define TRUE 1
33     #define FALSE 0
34     #endif
35    
36     #define SCARD_CTL_CODE(code) (0x42000000 + (code))
37    
38     #define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1)
39     #define IOCTL_SMARTCARD_VENDOR_VERIFY_PIN SCARD_CTL_CODE(2)
40     #define IOCTL_SMARTCARD_VENDOR_MODIFY_PIN SCARD_CTL_CODE(3)
41     #define IOCTL_SMARTCARD_VENDOR_TRANSFER_PIN SCARD_CTL_CODE(4)
42    
43     /* PCSC error message pretty print */
44     #define PCSC_ERROR_EXIT(rv, text) \
45     if (rv != SCARD_S_SUCCESS) \
46     { \
47     printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
48     goto end; \
49     } \
50     else \
51     printf(text ": OK\n\n");
52    
53     #define PCSC_ERROR_CONT(rv, text) \
54     if (rv != SCARD_S_SUCCESS) \
55     printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
56     else \
57     printf(text ": OK\n\n");
58    
59     int main(int argc, char *argv[])
60     {
61     LONG rv;
62     SCARDCONTEXT hContext;
63     DWORD dwReaders;
64 rousseau 972 LPTSTR mszReaders;
65 rousseau 889 char *ptr, **readers = NULL;
66     int nbReaders;
67     SCARDHANDLE hCard;
68     DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
69     BYTE pbAtr[MAX_ATR_SIZE] = "";
70 rousseau 892 char pbReader[MAX_READERNAME] = "";
71 rousseau 889 int reader_nb;
72     int i, offset;
73     unsigned char bSendBuffer[MAX_BUFFER_SIZE];
74     unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
75     DWORD length;
76 rousseau 1014 unsigned char attribute[1];
77 rousseau 903 DWORD attribute_length;
78 rousseau 972 SCARD_IO_REQUEST pioRecvPci;
79 rousseau 889
80     printf("SCardControl sample code\n");
81     printf("V 1.0 2004, Ludovic Rousseau <ludovic.rousseau@free.fr>\n");
82    
83 rousseau 1263 printf("\nTHIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL!\n");
84     printf("Do NOT use it unless you really know what you do.\n\n");
85    
86 rousseau 889 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
87     if (rv != SCARD_S_SUCCESS)
88     {
89     printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
90     return 1;
91     }
92    
93     /* Retrieve the available readers list */
94     rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
95     if (rv != SCARD_S_SUCCESS)
96     {
97     printf("SCardListReader: %lX\n", rv);
98     }
99    
100     mszReaders = malloc(sizeof(char)*dwReaders);
101     if (mszReaders == NULL)
102     {
103     printf("malloc: not enough memory\n");
104     goto end;
105     }
106    
107     rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
108     if (rv != SCARD_S_SUCCESS)
109     printf("SCardListReader: %lX\n", rv);
110    
111     /* Extract readers from the null separated string and get the total
112     * number of readers */
113     nbReaders = 0;
114     ptr = mszReaders;
115     while (*ptr != '\0')
116     {
117     ptr += strlen(ptr)+1;
118     nbReaders++;
119     }
120    
121     if (nbReaders == 0)
122     {
123     printf("No reader found\n");
124     goto end;
125     }
126    
127     /* allocate the readers table */
128     readers = calloc(nbReaders, sizeof(char *));
129     if (NULL == readers)
130     {
131     printf("Not enough memory for readers[]\n");
132     goto end;
133     }
134    
135     /* fill the readers table */
136     nbReaders = 0;
137     ptr = mszReaders;
138     while (*ptr != '\0')
139     {
140     printf("%d: %s\n", nbReaders, ptr);
141     readers[nbReaders] = ptr;
142     ptr += strlen(ptr)+1;
143     nbReaders++;
144     }
145    
146     if (argc > 1)
147     {
148     reader_nb = atoi(argv[1]);
149     if (reader_nb < 0 || reader_nb >= nbReaders)
150     {
151     printf("Wrong reader index: %d\n", reader_nb);
152     goto end;
153     }
154     }
155     else
156     reader_nb = 0;
157    
158 rousseau 900 /* connect to a reader (even without a card) */
159 rousseau 889 dwActiveProtocol = -1;
160     rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_DIRECT,
161 rousseau 940 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
162 rousseau 889 printf(" Protocol: %ld\n", dwActiveProtocol);
163     PCSC_ERROR_EXIT(rv, "SCardConnect")
164    
165 rousseau 972 /* get GemPC firmware */
166     printf(" Get GemPC Firmware\n");
167 rousseau 889
168     /* this is specific to Gemplus readers */
169     bSendBuffer[0] = 0x02;
170     rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
171     1, bRecvBuffer, sizeof(bRecvBuffer), &length);
172    
173     printf(" Firmware: ");
174     for (i=0; i<length; i++)
175     printf("%02X ", bRecvBuffer[i]);
176     printf("\n");
177    
178     bRecvBuffer[length] = '\0';
179     printf(" Firmware: %s (length %ld bytes)\n", bRecvBuffer, length);
180    
181     PCSC_ERROR_CONT(rv, "SCardControl")
182    
183     /* get card status */
184     dwAtrLen = sizeof(pbAtr);
185     dwReaderLen = sizeof(pbReader);
186     rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
187     pbAtr, &dwAtrLen);
188     printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
189     printf(" State: 0x%lX\n", dwState);
190     printf(" Prot: %ld\n", dwProt);
191     printf(" ATR (length %ld bytes):", dwAtrLen);
192     for (i=0; i<dwAtrLen; i++)
193     printf(" %02X", pbAtr[i]);
194     printf("\n");
195     PCSC_ERROR_CONT(rv, "SCardStatus")
196    
197 rousseau 900 /* does the reader support PIN verification? */
198     attribute_length = sizeof(attribute);
199     rv = SCardGetAttrib(hCard, IOCTL_SMARTCARD_VENDOR_VERIFY_PIN, attribute,
200     &attribute_length);
201     PCSC_ERROR_CONT(rv, "SCardGetAttrib")
202     if (FALSE == attribute[0])
203     {
204     printf("Reader %s does not support PIN verification\n",
205     readers[reader_nb]);
206     goto end;
207     }
208    
209 rousseau 972 /* connect to a reader (even without a card) */
210     dwActiveProtocol = -1;
211     rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
212     SCARD_PROTOCOL_T0, SCARD_UNPOWER_CARD, &dwActiveProtocol);
213     printf(" Protocol: %ld\n", dwActiveProtocol);
214     PCSC_ERROR_EXIT(rv, "SCardReconnect")
215    
216     /* APDU select DF */
217     memcpy(bSendBuffer, "\x00\xA4\x04\x00\x05\x47\x54\x4F\x4B\x31", 10);
218     length = sizeof(bRecvBuffer);
219     rv = SCardTransmit(hCard, SCARD_PCI_T0, bSendBuffer, 10,
220     &pioRecvPci, bRecvBuffer, &length);
221     printf(" card response:");
222     for (i=0; i<length; i++)
223     printf(" %02X", bRecvBuffer[i]);
224     printf("\n");
225     PCSC_ERROR_EXIT(rv, "SCardTransmit")
226    
227     /* APDU select EF */
228     memcpy(bSendBuffer, "\x00\xA4\x02\x00\x02\x00\x04", 7);
229     length = sizeof(bRecvBuffer);
230     rv = SCardTransmit(hCard, SCARD_PCI_T0, bSendBuffer, 7,
231     &pioRecvPci, bRecvBuffer, &length);
232     printf(" card response:");
233     for (i=0; i<length; i++)
234     printf(" %02X", bRecvBuffer[i]);
235     printf("\n");
236     PCSC_ERROR_EXIT(rv, "SCardTransmit")
237    
238 rousseau 889 /* verify PIN */
239     printf(" Secure verify PIN\n");
240     offset = 0;
241     /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
242     bSendBuffer[offset++] = 0x00; /* CLA */
243     bSendBuffer[offset++] = 0x20; /* INS: VERIFY */
244     bSendBuffer[offset++] = 0x00; /* P1 */
245     bSendBuffer[offset++] = 0x00; /* P2 */
246     bSendBuffer[offset++] = 0x08; /* Lc: 8 data bytes */
247     bSendBuffer[offset++] = 0x30; /* '0' */
248     bSendBuffer[offset++] = 0x30; /* '0' */
249     bSendBuffer[offset++] = 0x30; /* '0' */
250     bSendBuffer[offset++] = 0x30; /* '0' */
251     bSendBuffer[offset++] = 0x00; /* '\0' */
252     bSendBuffer[offset++] = 0x00; /* '\0' */
253     bSendBuffer[offset++] = 0x00; /* '\0' */
254     bSendBuffer[offset++] = 0x00; /* '\0' */
255    
256     /* CCID PIN verification data structure */
257     bSendBuffer[offset++] = 0x00; /* bTimeOut */
258     bSendBuffer[offset++] = 0x82; /* bmFormatString */
259     bSendBuffer[offset++] = 0x04; /* bmPINBlockString (PIN length) */
260     bSendBuffer[offset++] = 0x00; /* bmPINLengthFormat */
261 rousseau 1290 bSendBuffer[offset++] = 0x08; /* wPINMaxExtraDigit: max */
262 rousseau 889 bSendBuffer[offset++] = 0x04; /* wPINMaxExtraDigit: min */
263     bSendBuffer[offset++] = 0x02; /* bEntryValidationCondition */
264     bSendBuffer[offset++] = 0x00; /* bNumberMessage */
265     bSendBuffer[offset++] = 0x04; /* wLangId: english */
266 rousseau 903 bSendBuffer[offset++] = 0x09; /* " */
267 rousseau 889 bSendBuffer[offset++] = 0x00; /* bMsgIndex */
268     bSendBuffer[offset++] = 0x00; /* bTeoPrologue */
269 rousseau 903 bSendBuffer[offset++] = 0x00; /* " */
270     bSendBuffer[offset++] = 0x00; /* " */
271 rousseau 889
272     printf(" command:");
273     for (i=0; i<offset; i++)
274     printf(" %02X", bSendBuffer[i]);
275     printf("\n");
276 rousseau 972 printf("Enter your PIN: ");
277 rousseau 900 fflush(stdout);
278 rousseau 889 rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_VERIFY_PIN, bSendBuffer,
279     offset, bRecvBuffer, sizeof(bRecvBuffer), &length);
280    
281     printf(" card response:");
282     for (i=0; i<length; i++)
283     printf(" %02X", bRecvBuffer[i]);
284     printf("\n");
285     PCSC_ERROR_CONT(rv, "SCardControl")
286    
287 rousseau 972 {
288 rousseau 1067 #ifndef S_SPLINT_S
289 rousseau 972 fd_set fd;
290 rousseau 1067 #endif
291 rousseau 972 struct timeval timeout;
292    
293     FD_ZERO(&fd);
294     FD_SET(STDIN_FILENO, &fd); /* stdin */
295     timeout.tv_sec = 0; /* timeout = 0 */
296     timeout.tv_usec = 0;
297    
298     /* we only try to read stdin if the pinpad is on a keyboard
299     * we do not read stdin for a SPR 532 for example */
300     if (select(1, &fd, NULL, NULL, &timeout) > 0)
301     {
302     /* read the fake digits */
303     char in[10]; /* 4 digits + \n + \0 */
304 rousseau 1059 (void)fgets(in, sizeof(in), stdin);
305 rousseau 972
306     printf("keyboard sent: %s", in);
307     }
308     }
309    
310 rousseau 889 /* card disconnect */
311     rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
312     PCSC_ERROR_CONT(rv, "SCardDisconnect")
313    
314     end:
315     /* We try to leave things as clean as possible */
316     rv = SCardReleaseContext(hContext);
317     if (rv != SCARD_S_SUCCESS)
318     printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
319     rv);
320    
321     /* free allocated memory */
322     free(mszReaders);
323     free(readers);
324    
325     return 0;
326     } /* main */
327    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5