/[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 6074 - (show annotations) (download)
Mon Oct 24 12:26:49 2011 UTC (18 months, 3 weeks ago) by rousseau
File MIME type: text/plain
File size: 23712 byte(s)
Display PIN_PROPERTIES_STRUCTURE if any
1 /*
2 scardcontrol.c: sample code to use/test SCardControl() API
3 Copyright (C) 2004-2011 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 along
16 with this program; if not, write to the Free Software Foundation, Inc., 51
17 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21 * $Id$
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/time.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <arpa/inet.h>
30 #ifdef __APPLE__
31 #include <PCSC/winscard.h>
32 #include <PCSC/wintypes.h>
33 #else
34 #include <winscard.h>
35 #endif
36 #include <reader.h>
37
38 #undef VERIFY_PIN
39 #define MODIFY_PIN
40 #undef GET_GEMPC_FIRMWARE
41
42 #ifndef TRUE
43 #define TRUE 1
44 #define FALSE 0
45 #endif
46
47 #define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1)
48
49 #define BLUE "\33[34m"
50 #define RED "\33[31m"
51 #define BRIGHT_RED "\33[01;31m"
52 #define GREEN "\33[32m"
53 #define NORMAL "\33[0m"
54 #define MAGENTA "\33[35m"
55
56 /* PCSC error message pretty print */
57 #define PCSC_ERROR_EXIT(rv, text) \
58 if (rv != SCARD_S_SUCCESS) \
59 { \
60 printf(text ": " RED "%s (0x%lX)\n" NORMAL, pcsc_stringify_error(rv), rv); \
61 goto end; \
62 } \
63 else \
64 printf(text ": " BLUE "OK\n\n" NORMAL);
65
66 #define PCSC_ERROR_CONT(rv, text) \
67 if (rv != SCARD_S_SUCCESS) \
68 printf(text ": " BLUE "%s (0x%lX)\n" NORMAL, pcsc_stringify_error(rv), rv); \
69 else \
70 printf(text ": " BLUE "OK\n\n" NORMAL);
71
72 #define PRINT_GREEN(text, value) \
73 printf("%s: " GREEN "%s\n" NORMAL, text, value)
74
75 #define PRINT_GREEN_DEC(text, value) \
76 printf("%s: " GREEN "%d\n" NORMAL, text, value)
77
78 #define PRINT_GREEN_HEX2(text, value) \
79 printf("%s: " GREEN "0x%02X\n" NORMAL, text, value)
80
81 #define PRINT_GREEN_HEX4(text, value) \
82 printf("%s: " GREEN "0x%04X\n" NORMAL, text, value)
83
84 static void parse_properties(unsigned char *bRecvBuffer, int length)
85 {
86 unsigned char *p;
87 int i;
88
89 p = bRecvBuffer;
90 while (p-bRecvBuffer < length)
91 {
92 int tag, len, value;
93
94 tag = *p++;
95 len = *p++;
96
97 switch(len)
98 {
99 case 1:
100 value = *p;
101 break;
102 case 2:
103 value = *p + (*(p+1)<<8);
104 break;
105 case 4:
106 value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24);
107 break;
108 default:
109 value = -1;
110 }
111
112 switch(tag)
113 {
114 case PCSCv2_PART10_PROPERTY_wLcdLayout:
115 PRINT_GREEN_HEX4(" wLcdLayout", value);
116 break;
117 case PCSCv2_PART10_PROPERTY_bEntryValidationCondition:
118 PRINT_GREEN_HEX2(" bEntryValidationCondition", value);
119 break;
120 case PCSCv2_PART10_PROPERTY_bTimeOut2:
121 PRINT_GREEN_HEX2(" bTimeOut2", value);
122 break;
123 case PCSCv2_PART10_PROPERTY_wLcdMaxCharacters:
124 PRINT_GREEN_HEX4(" wLcdMaxCharacters", value);
125 break;
126 case PCSCv2_PART10_PROPERTY_wLcdMaxLines:
127 PRINT_GREEN_HEX4(" wLcdMaxLines", value);
128 break;
129 case PCSCv2_PART10_PROPERTY_bMinPINSize:
130 PRINT_GREEN_HEX2(" bMinPINSize", value);
131 break;
132 case PCSCv2_PART10_PROPERTY_bMaxPINSize:
133 PRINT_GREEN_HEX2(" bMaxPINSize", value);
134 break;
135 case PCSCv2_PART10_PROPERTY_sFirmwareID:
136 printf(" sFirmwareID: " GREEN);
137 for (i=0; i<len; i++)
138 putchar(p[i]);
139 printf(NORMAL "\n");
140 break;
141 case PCSCv2_PART10_PROPERTY_bPPDUSupport:
142 PRINT_GREEN_HEX2(" bPPDUSupport", value);
143 if (value & 1)
144 printf(" PPDU is supported over SCardControl using FEATURE_CCID_ESC_COMMAND\n");
145 if (value & 2)
146 printf(" PPDU is supported over SCardTransmit\n");
147 break;
148 default:
149 printf(" Unknown tag: 0x%02X (length = %d)\n", tag, len);
150 }
151
152 p += len;
153 }
154 } /* parse_properties */
155
156 static int find_property_by_tag(unsigned char *bRecvBuffer, int length,
157 int tag_searched)
158 {
159 unsigned char *p;
160 int found = 0, len, value = -1;
161
162 p = bRecvBuffer;
163 while (p-bRecvBuffer < length)
164 {
165 if (*p++ == tag_searched)
166 {
167 found = 1;
168 break;
169 }
170
171 /* go to next tag */
172 len = *p++;
173 p += len;
174 }
175
176 if (found)
177 {
178 len = *p++;
179
180 switch(len)
181 {
182 case 1:
183 value = *p;
184 break;
185 case 2:
186 value = *p + (*(p+1)<<8);
187 break;
188 case 4:
189 value = *p + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24);
190 break;
191 default:
192 value = -1;
193 }
194 }
195
196 return value;
197 } /* find_property_by_tag */
198
199 int main(int argc, char *argv[])
200 {
201 LONG rv;
202 SCARDCONTEXT hContext;
203 DWORD dwReaders;
204 LPSTR mszReaders = NULL;
205 char *ptr, **readers = NULL;
206 int nbReaders;
207 SCARDHANDLE hCard;
208 DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
209 BYTE pbAtr[MAX_ATR_SIZE] = "";
210 char pbReader[MAX_READERNAME] = "";
211 int reader_nb;
212 unsigned int i;
213 unsigned char bSendBuffer[MAX_BUFFER_SIZE];
214 unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
215 DWORD send_length, length;
216 DWORD verify_ioctl = 0;
217 DWORD modify_ioctl = 0;
218 DWORD pin_properties_ioctl = 0;
219 DWORD mct_readerdirect_ioctl = 0;
220 DWORD properties_in_tlv_ioctl = 0;
221 DWORD ccid_esc_command = 0;
222 SCARD_IO_REQUEST pioRecvPci;
223 SCARD_IO_REQUEST pioSendPci;
224 PCSC_TLV_STRUCTURE *pcsc_tlv;
225 #if defined(VERIFY_PIN) | defined(MODIFY_PIN)
226 int offset;
227 #endif
228 #ifdef VERIFY_PIN
229 PIN_VERIFY_STRUCTURE *pin_verify;
230 #endif
231 #ifdef MODIFY_PIN
232 PIN_MODIFY_STRUCTURE *pin_modify;
233 #endif
234 char secoder_info[] = { 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
235
236 printf("SCardControl sample code\n");
237 printf("V 1.4 © 2004-2010, Ludovic Rousseau <ludovic.rousseau@free.fr>\n\n");
238
239 printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL!\n");
240 printf("Do NOT use it unless you really know what you do.\n\n" NORMAL);
241
242 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
243 if (rv != SCARD_S_SUCCESS)
244 {
245 printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
246 return 1;
247 }
248
249 /* Retrieve the available readers list */
250 rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
251 PCSC_ERROR_EXIT(rv, "SCardListReaders")
252
253 mszReaders = malloc(sizeof(char)*dwReaders);
254 if (mszReaders == NULL)
255 {
256 printf("malloc: not enough memory\n");
257 goto end;
258 }
259
260 rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
261 if (rv != SCARD_S_SUCCESS)
262 printf("SCardListReader: %lX\n", rv);
263
264 /* Extract readers from the null separated string and get the total
265 * number of readers */
266 nbReaders = 0;
267 ptr = mszReaders;
268 while (*ptr != '\0')
269 {
270 ptr += strlen(ptr)+1;
271 nbReaders++;
272 }
273
274 if (nbReaders == 0)
275 {
276 printf("No reader found\n");
277 goto end;
278 }
279
280 /* allocate the readers table */
281 readers = calloc(nbReaders, sizeof(char *));
282 if (NULL == readers)
283 {
284 printf("Not enough memory for readers[]\n");
285 goto end;
286 }
287
288 /* fill the readers table */
289 nbReaders = 0;
290 ptr = mszReaders;
291 printf("Available readers (use command line argument to select)\n");
292 while (*ptr != '\0')
293 {
294 printf("%d: %s\n", nbReaders, ptr);
295 readers[nbReaders] = ptr;
296 ptr += strlen(ptr)+1;
297 nbReaders++;
298 }
299 printf("\n");
300
301 if (argc > 1)
302 {
303 reader_nb = atoi(argv[1]);
304 if (reader_nb < 0 || reader_nb >= nbReaders)
305 {
306 printf("Wrong reader index: %d\n", reader_nb);
307 goto end;
308 }
309 }
310 else
311 reader_nb = 0;
312
313 /* connect to a reader (even without a card) */
314 dwActiveProtocol = -1;
315 printf("Using reader: " GREEN "%s\n" NORMAL, readers[reader_nb]);
316 rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
317 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
318 printf(" Protocol: " GREEN "%ld\n" NORMAL, dwActiveProtocol);
319 PCSC_ERROR_EXIT(rv, "SCardConnect")
320
321 #ifdef GET_GEMPC_FIRMWARE
322 /* get GemPC firmware */
323 printf(" Get GemPC Firmware\n");
324
325 /* this is specific to Gemalto readers */
326 bSendBuffer[0] = 0x02;
327 rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
328 1, bRecvBuffer, sizeof(bRecvBuffer), &length);
329
330 printf(" Firmware: " GREEN);
331 for (i=0; i<length; i++)
332 printf("%02X ", bRecvBuffer[i]);
333 printf(NORMAL "\n");
334
335 bRecvBuffer[length] = '\0';
336 printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);
337
338 PCSC_ERROR_CONT(rv, "SCardControl")
339 #endif
340
341 /* does the reader support PIN verification? */
342 rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
343 bRecvBuffer, sizeof(bRecvBuffer), &length);
344 PCSC_ERROR_EXIT(rv, "SCardControl")
345
346 printf(" TLV (%ld): " GREEN, length);
347 for (i=0; i<length; i++)
348 printf("%02X ", bRecvBuffer[i]);
349 printf(NORMAL "\n");
350
351 PCSC_ERROR_CONT(rv, "SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)")
352
353 if (length % sizeof(PCSC_TLV_STRUCTURE))
354 {
355 printf("Inconsistent result! Bad TLV values!\n");
356 goto end;
357 }
358
359 /* get the number of elements instead of the complete size */
360 length /= sizeof(PCSC_TLV_STRUCTURE);
361
362 pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
363 for (i = 0; i < length; i++)
364 {
365 switch (pcsc_tlv[i].tag)
366 {
367 case FEATURE_VERIFY_PIN_DIRECT:
368 PRINT_GREEN("Reader supports", "FEATURE_VERIFY_PIN_DIRECT");
369 verify_ioctl = ntohl(pcsc_tlv[i].value);
370 break;
371 case FEATURE_MODIFY_PIN_DIRECT:
372 PRINT_GREEN("Reader supports", "FEATURE_MODIFY_PIN_DIRECT");
373 modify_ioctl = ntohl(pcsc_tlv[i].value);
374 break;
375 case FEATURE_IFD_PIN_PROPERTIES:
376 PRINT_GREEN("Reader supports", "FEATURE_IFD_PIN_PROPERTIES");
377 pin_properties_ioctl = ntohl(pcsc_tlv[i].value);
378 break;
379 case FEATURE_MCT_READER_DIRECT:
380 PRINT_GREEN("Reader supports", "FEATURE_MCT_READER_DIRECT");
381 mct_readerdirect_ioctl = ntohl(pcsc_tlv[i].value);
382 break;
383 case FEATURE_GET_TLV_PROPERTIES:
384 PRINT_GREEN("Reader supports", "FEATURE_GET_TLV_PROPERTIES");
385 properties_in_tlv_ioctl = ntohl(pcsc_tlv[i].value);
386 break;
387 case FEATURE_CCID_ESC_COMMAND:
388 PRINT_GREEN("Reader supports", "FEATURE_CCID_ESC_COMMAND");
389 ccid_esc_command = ntohl(pcsc_tlv[i].value);
390 break;
391 default:
392 printf("Can't parse tag: " RED "0x%02X" NORMAL, pcsc_tlv[i].tag);
393 }
394 }
395 printf("\n");
396
397 if (properties_in_tlv_ioctl)
398 {
399 int value;
400
401 rv = SCardControl(hCard, properties_in_tlv_ioctl, NULL, 0,
402 bRecvBuffer, sizeof(bRecvBuffer), &length);
403 PCSC_ERROR_CONT(rv, "SCardControl(GET_TLV_PROPERTIES)")
404
405 printf("GET_TLV_PROPERTIES (" GREEN "%ld" NORMAL "): " GREEN, length);
406 for (i=0; i<length; i++)
407 printf("%02X ", bRecvBuffer[i]);
408 printf(NORMAL "\n");
409
410 printf("\nDisplay all the properties:\n");
411 parse_properties(bRecvBuffer, length);
412
413 printf("\nFind a specific property:\n");
414 value = find_property_by_tag(bRecvBuffer, length, PCSCv2_PART10_PROPERTY_bEntryValidationCondition);
415 PRINT_GREEN_DEC(" bEntryValidationCondition", value);
416
417 value = find_property_by_tag(bRecvBuffer, length, PCSCv2_PART10_PROPERTY_bMaxPINSize);
418 PRINT_GREEN_DEC(" bMaxPINSize", value);
419
420 printf("\n");
421 }
422
423 if (mct_readerdirect_ioctl)
424 {
425 rv = SCardControl(hCard, mct_readerdirect_ioctl, secoder_info,
426 sizeof(secoder_info), bRecvBuffer, sizeof(bRecvBuffer), &length);
427 PCSC_ERROR_CONT(rv, "SCardControl(MCT_READER_DIRECT)")
428
429 printf("MCT_READER_DIRECT (%ld): ", length);
430 for (i=0; i<length; i++)
431 printf("%02X ", bRecvBuffer[i]);
432 printf("\n");
433 }
434
435 if (pin_properties_ioctl)
436 {
437 PIN_PROPERTIES_STRUCTURE *pin_properties;
438
439 rv = SCardControl(hCard, pin_properties_ioctl, NULL, 0,
440 bRecvBuffer, sizeof(bRecvBuffer), &length);
441 PCSC_ERROR_CONT(rv, "SCardControl(pin_properties_ioctl)")
442
443 printf("PIN PROPERTIES (" GREEN "%ld" NORMAL "): " GREEN, length);
444 for (i=0; i<length; i++)
445 printf("%02X ", bRecvBuffer[i]);
446 printf(NORMAL "\n");
447
448 pin_properties = (PIN_PROPERTIES_STRUCTURE *)bRecvBuffer;
449 PRINT_GREEN_HEX4(" wLcdLayout", pin_properties -> wLcdLayout);
450 PRINT_GREEN_DEC(" bEntryValidationCondition", pin_properties -> bEntryValidationCondition);
451 PRINT_GREEN_DEC(" bTimeOut2", pin_properties -> bTimeOut2);
452
453 printf("\n");
454 }
455
456 #ifdef GET_GEMPC_FIRMWARE
457 if (ccid_esc_command)
458 {
459 /* get GemPC firmware */
460 printf("Get GemPC Firmware\n");
461
462 /* this is specific to Gemalto readers */
463 bSendBuffer[0] = 0x02;
464 rv = SCardControl(hCard, ccid_esc_command, bSendBuffer,
465 1, bRecvBuffer, sizeof(bRecvBuffer), &length);
466
467 printf(" Firmware: " GREEN);
468 for (i=0; i<length; i++)
469 printf("%02X ", bRecvBuffer[i]);
470 printf(NORMAL "\n");
471
472 bRecvBuffer[length] = '\0';
473 printf(" Firmware: " GREEN "%s" NORMAL" (length " GREEN "%ld" NORMAL " bytes)\n", bRecvBuffer, length);
474
475 PCSC_ERROR_CONT(rv, "SCardControl")
476 }
477 #endif
478
479 if (0 == verify_ioctl)
480 {
481 printf("Reader %s does not support PIN verification\n",
482 readers[reader_nb]);
483 goto end;
484 }
485
486 /* get card status */
487 dwAtrLen = sizeof(pbAtr);
488 dwReaderLen = sizeof(pbReader);
489 rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
490 pbAtr, &dwAtrLen);
491 printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
492 printf(" State: 0x%04lX\n", dwState);
493 printf(" Prot: %ld\n", dwProt);
494 printf(" ATR (length %ld bytes):", dwAtrLen);
495 for (i=0; i<dwAtrLen; i++)
496 printf(" %02X", pbAtr[i]);
497 printf("\n");
498 PCSC_ERROR_CONT(rv, "SCardStatus")
499
500 if (dwState & SCARD_ABSENT)
501 {
502 printf("No card inserted\n");
503 goto end;
504 }
505
506 /* connect to a reader (even without a card) */
507 dwActiveProtocol = -1;
508 rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
509 SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
510 &dwActiveProtocol);
511 printf(" Protocol: %ld\n", dwActiveProtocol);
512 PCSC_ERROR_EXIT(rv, "SCardReconnect")
513
514 switch(dwActiveProtocol)
515 {
516 case SCARD_PROTOCOL_T0:
517 pioSendPci = *SCARD_PCI_T0;
518 break;
519 case SCARD_PROTOCOL_T1:
520 pioSendPci = *SCARD_PCI_T1;
521 break;
522 default:
523 printf("Unknown protocol. No card present?\n");
524 return -1;
525 }
526
527 /* APDU select applet */
528 printf("Select applet: ");
529 send_length = 11;
530 memcpy(bSendBuffer, "\x00\xA4\x04\x00\x06\xA0\x00\x00\x00\x18\xFF",
531 send_length);
532 for (i=0; i<send_length; i++)
533 printf(" %02X", bSendBuffer[i]);
534 printf("\n");
535 length = sizeof(bRecvBuffer);
536 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
537 &pioRecvPci, bRecvBuffer, &length);
538 printf(" card response:");
539 for (i=0; i<length; i++)
540 printf(" %02X", bRecvBuffer[i]);
541 printf("\n");
542 PCSC_ERROR_EXIT(rv, "SCardTransmit")
543 if ((bRecvBuffer[0] != 0x90) || (bRecvBuffer[1] != 0x00))
544 {
545 printf("Error: test applet not found!\n");
546 goto end;
547 }
548
549 #ifdef VERIFY_PIN
550 /* verify PIN */
551 printf(" Secure verify PIN\n");
552 pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;
553
554 /* table for bEntryValidationCondition
555 * 0x01: Max size reached
556 * 0x02: Validation key pressed
557 * 0x04: Timeout occured
558 */
559 /* PC/SC v2.02.05 Part 10 PIN verification data structure */
560 pin_verify -> bTimerOut = 0x00;
561 pin_verify -> bTimerOut2 = 0x00;
562 pin_verify -> bmFormatString = 0x82;
563 pin_verify -> bmPINBlockString = 0x04;
564 pin_verify -> bmPINLengthFormat = 0x00;
565 pin_verify -> wPINMaxExtraDigit = 0x0408; /* Min Max */
566 pin_verify -> bEntryValidationCondition = 0x02; /* validation key pressed */
567 pin_verify -> bNumberMessage = 0x01;
568 pin_verify -> wLangId = 0x0904;
569 pin_verify -> bMsgIndex = 0x00;
570 pin_verify -> bTeoPrologue[0] = 0x00;
571 pin_verify -> bTeoPrologue[1] = 0x00;
572 pin_verify -> bTeoPrologue[2] = 0x00;
573 /* pin_verify -> ulDataLength = 0x00; we don't know the size yet */
574
575 /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
576 offset = 0;
577 pin_verify -> abData[offset++] = 0x00; /* CLA */
578 pin_verify -> abData[offset++] = 0x20; /* INS: VERIFY */
579 pin_verify -> abData[offset++] = 0x00; /* P1 */
580 pin_verify -> abData[offset++] = 0x00; /* P2 */
581 pin_verify -> abData[offset++] = 0x08; /* Lc: 8 data bytes */
582 pin_verify -> abData[offset++] = 0x30; /* '0' */
583 pin_verify -> abData[offset++] = 0x30; /* '0' */
584 pin_verify -> abData[offset++] = 0x30; /* '0' */
585 pin_verify -> abData[offset++] = 0x30; /* '0' */
586 pin_verify -> abData[offset++] = 0x00; /* '\0' */
587 pin_verify -> abData[offset++] = 0x00; /* '\0' */
588 pin_verify -> abData[offset++] = 0x00; /* '\0' */
589 pin_verify -> abData[offset++] = 0x00; /* '\0' */
590 pin_verify -> ulDataLength = offset; /* APDU size */
591
592 length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1; /* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */
593
594 printf(" command:");
595 for (i=0; i<length; i++)
596 printf(" %02X", bSendBuffer[i]);
597 printf("\n");
598 printf("Enter your PIN: ");
599 fflush(stdout);
600 rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
601 length, bRecvBuffer, sizeof(bRecvBuffer), &length);
602
603 {
604 #ifndef S_SPLINT_S
605 fd_set fd;
606 #endif
607 struct timeval timeout;
608
609 FD_ZERO(&fd);
610 FD_SET(STDIN_FILENO, &fd); /* stdin */
611 timeout.tv_sec = 0; /* timeout = 0.1s */
612 timeout.tv_usec = 100000;
613
614 /* we only try to read stdin if the pinpad is on a keyboard
615 * we do not read stdin for a SPR 532 for example */
616 if (select(1, &fd, NULL, NULL, &timeout) > 0)
617 {
618 /* read the fake digits */
619 char in[40]; /* 4 digits + \n + \0 */
620 (void)fgets(in, sizeof(in), stdin);
621
622 printf("keyboard sent: %s", in);
623 }
624 else
625 /* if it is not a keyboard */
626 printf("\n");
627 }
628
629 printf(" card response:");
630 for (i=0; i<length; i++)
631 printf(" %02X", bRecvBuffer[i]);
632 printf("\n");
633 PCSC_ERROR_CONT(rv, "SCardControl")
634
635 /* verify PIN dump */
636 printf("\nverify PIN dump: ");
637 send_length = 5;
638 memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
639 send_length);
640 for (i=0; i<send_length; i++)
641 printf(" %02X", bSendBuffer[i]);
642 printf("\n");
643 length = sizeof(bRecvBuffer);
644 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
645 &pioRecvPci, bRecvBuffer, &length);
646 printf(" card response:");
647 for (i=0; i<length; i++)
648 printf(" %02X", bRecvBuffer[i]);
649 printf("\n");
650 PCSC_ERROR_EXIT(rv, "SCardTransmit")
651
652 if ((2 == length) && (0x6C == bRecvBuffer[0]))
653 {
654 printf("\nverify PIN dump: ");
655 send_length = 5;
656 memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
657 send_length);
658 bSendBuffer[4] = bRecvBuffer[1];
659 for (i=0; i<send_length; i++)
660 printf(" %02X", bSendBuffer[i]);
661 printf("\n");
662 length = sizeof(bRecvBuffer);
663 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
664 &pioRecvPci, bRecvBuffer, &length);
665 printf(" card response:");
666 for (i=0; i<length; i++)
667 printf(" %02X", bRecvBuffer[i]);
668 printf("\n");
669 PCSC_ERROR_EXIT(rv, "SCardTransmit")
670 }
671 #endif
672
673 /* check if the reader supports Modify PIN */
674 if (0 == modify_ioctl)
675 {
676 printf("Reader %s does not support PIN modification\n",
677 readers[reader_nb]);
678 goto end;
679 }
680
681 #ifdef MODIFY_PIN
682 /* Modify PIN */
683 printf(" Secure modify PIN\n");
684 pin_modify = (PIN_MODIFY_STRUCTURE *)bSendBuffer;
685
686 /* Table for bConfirmPIN and bNumberMessage
687 * bConfirmPIN = 3, bNumberMessage = 3: "Enter Pin" "New Pin" "Confirm Pin"
688 * bConfirmPIN = 2, bNumberMessage = 2: "Enter Pin" "New Pin"
689 * bConfirmPIN = 1, bNumberMessage = 2: "New Pin" "Confirm Pin"
690 * bConfirmPIN = 0, bNumberMessage = 1: "New Pin"
691 */
692 /* table for bMsgIndex[1-3]
693 * 00: PIN insertion prompt “ENTER SMARTCARD PIN”
694 * 01: PIN Modification prompt “ ENTER NEW PIN”
695 * 02: NEW PIN Confirmation prompt “ CONFIRM NEW PIN”
696 */
697 /* PC/SC v2.02.05 Part 10 PIN modification data structure */
698 pin_modify -> bTimerOut = 0x00;
699 pin_modify -> bTimerOut2 = 0x00;
700 pin_modify -> bmFormatString = 0x82;
701 pin_modify -> bmPINBlockString = 0x04;
702 pin_modify -> bmPINLengthFormat = 0x00;
703 pin_modify -> bInsertionOffsetOld = 0x00; /* offset from APDU start */
704 pin_modify -> bInsertionOffsetNew = 0x04; /* offset from APDU start */
705 pin_modify -> wPINMaxExtraDigit = 0x0408; /* Min Max */
706 pin_modify -> bConfirmPIN = 0x03; /* b0 set = confirmation requested */
707 /* b1 set = current PIN entry requested */
708 pin_modify -> bEntryValidationCondition = 0x02; /* validation key pressed */
709 pin_modify -> bNumberMessage = 0x03; /* see table above */
710 pin_modify -> wLangId = 0x0904;
711 pin_modify -> bMsgIndex1 = 0x00;
712 pin_modify -> bMsgIndex2 = 0x01;
713 pin_modify -> bMsgIndex3 = 0x02;
714 pin_modify -> bTeoPrologue[0] = 0x00;
715 pin_modify -> bTeoPrologue[1] = 0x00;
716 pin_modify -> bTeoPrologue[2] = 0x00;
717 /* pin_modify -> ulDataLength = 0x00; we don't know the size yet */
718
719 /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
720 offset = 0;
721 pin_modify -> abData[offset++] = 0x00; /* CLA */
722 pin_modify -> abData[offset++] = 0x24; /* INS: CHANGE/UNBLOCK */
723 pin_modify -> abData[offset++] = 0x00; /* P1 */
724 pin_modify -> abData[offset++] = 0x00; /* P2 */
725 pin_modify -> abData[offset++] = 0x08; /* Lc: 2x8 data bytes */
726 pin_modify -> abData[offset++] = 0x30; /* '0' old PIN */
727 pin_modify -> abData[offset++] = 0x30; /* '0' */
728 pin_modify -> abData[offset++] = 0x30; /* '0' */
729 pin_modify -> abData[offset++] = 0x30; /* '0' */
730 pin_modify -> abData[offset++] = 0x30; /* '0' new PIN */
731 pin_modify -> abData[offset++] = 0x30; /* '0' */
732 pin_modify -> abData[offset++] = 0x30; /* '0' */
733 pin_modify -> abData[offset++] = 0x30; /* '0' */
734 pin_modify -> ulDataLength = offset; /* APDU size */
735
736 length = sizeof(PIN_MODIFY_STRUCTURE) + offset -1; /* -1 because PIN_MODIFY_STRUCTURE contains the first byte of abData[] */
737
738 printf(" command:");
739 for (i=0; i<length; i++)
740 printf(" %02X", bSendBuffer[i]);
741 printf("\n");
742 printf("Enter your PIN: ");
743 fflush(stdout);
744 rv = SCardControl(hCard, modify_ioctl, bSendBuffer,
745 length, bRecvBuffer, sizeof(bRecvBuffer), &length);
746
747 printf(" card response:");
748 for (i=0; i<length; i++)
749 printf(" %02X", bRecvBuffer[i]);
750 printf("\n");
751 PCSC_ERROR_CONT(rv, "SCardControl")
752
753 {
754 #ifndef S_SPLINT_S
755 fd_set fd;
756 #endif
757 struct timeval timeout;
758
759 /* old PIN, new PIN, confirmation PIN */
760 /* if the command is aborted we will not read every "PIN" */
761 for (i=0; i<3; i++)
762 {
763 FD_ZERO(&fd);
764 FD_SET(STDIN_FILENO, &fd); /* stdin */
765 timeout.tv_sec = 0; /* timeout = 0.1s */
766 timeout.tv_usec = 100000;
767
768 /* we only try to read stdin if the pinpad is on a keyboard
769 * we do not read stdin for a SPR 532 for example */
770 if (select(1, &fd, NULL, NULL, &timeout) > 0)
771 {
772 /* read the fake digits */
773 char in[40]; /* 4 digits + \n + \0 */
774
775 (void)fgets(in, sizeof(in), stdin);
776 printf("keyboard sent: %s", in);
777 }
778 }
779 }
780
781 /* modify PIN dump */
782 printf("\nmodify PIN dump: ");
783 send_length = 5;
784 memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
785 send_length);
786 for (i=0; i<send_length; i++)
787 printf(" %02X", bSendBuffer[i]);
788 printf("\n");
789 length = sizeof(bRecvBuffer);
790 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
791 &pioRecvPci, bRecvBuffer, &length);
792 printf(" card response:");
793 for (i=0; i<length; i++)
794 printf(" %02X", bRecvBuffer[i]);
795 printf("\n");
796 PCSC_ERROR_EXIT(rv, "SCardTransmit")
797
798 if ((2 == length) && (0x6C == bRecvBuffer[0]))
799 {
800 printf("\nverify PIN dump: ");
801 send_length = 5;
802 memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
803 send_length);
804 bSendBuffer[4] = bRecvBuffer[1];
805 for (i=0; i<send_length; i++)
806 printf(" %02X", bSendBuffer[i]);
807 printf("\n");
808 length = sizeof(bRecvBuffer);
809 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
810 &pioRecvPci, bRecvBuffer, &length);
811 printf(" card response:");
812 for (i=0; i<length; i++)
813 printf(" %02X", bRecvBuffer[i]);
814 printf("\n");
815 PCSC_ERROR_EXIT(rv, "SCardTransmit")
816 }
817 #endif
818
819 /* card disconnect */
820 rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
821 PCSC_ERROR_CONT(rv, "SCardDisconnect")
822
823 end:
824 /* We try to leave things as clean as possible */
825 rv = SCardReleaseContext(hContext);
826 if (rv != SCARD_S_SUCCESS)
827 printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
828 rv);
829
830 /* free allocated memory */
831 if (mszReaders)
832 free(mszReaders);
833 if (readers)
834 free(readers);
835
836 return 0;
837 } /* main */
838

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5