/[pcsclite]/trunk/Drivers/ccid/src/ifdhandler.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/ifdhandler.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1058 - (hide annotations) (download)
Fri Jul 9 14:06:58 2004 UTC (8 years, 10 months ago) by rousseau
File MIME type: text/plain
File size: 24481 byte(s)
IFDHSetProtocolParameters(): test the return value of SetParameters()
1 rousseau 269 /*
2     ifdhandler.c: IFDH API
3     Copyright (C) 2003 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 rousseau 773 /* $Id$ */
21 rousseau 770
22 rousseau 269 #include <stdio.h>
23     #include <string.h>
24 rousseau 773 #include <stdlib.h>
25 rousseau 998 #include <PCSC/pcsclite.h>
26     #include <PCSC/ifdhandler.h>
27 rousseau 269
28 rousseau 880 #include "ccid.h"
29 rousseau 611 #include "defs.h"
30 rousseau 880 #include "ccid_ifdhandler.h"
31 rousseau 269 #include "config.h"
32     #include "debug.h"
33     #include "utils.h"
34     #include "commands.h"
35 rousseau 998 #include "towitoko/atr.h"
36     #include "towitoko/pps.h"
37 rousseau 773 #include "parser.h"
38 rousseau 269
39 rousseau 563 #ifdef HAVE_PTHREAD
40 rousseau 463 #include <pthread.h>
41     #endif
42    
43 rousseau 410 /* Array of structures to hold the ATR and other state value of each slot */
44     static CcidDesc CcidSlots[PCSCLITE_MAX_READERS];
45 rousseau 269
46 rousseau 463 /* global mutex */
47 rousseau 563 #ifdef HAVE_PTHREAD
48 rousseau 463 static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;
49     #endif
50 rousseau 269
51 rousseau 880 int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
52     int DriverOptions = 0;
53 rousseau 773 static int DebugInitialized = FALSE;
54 rousseau 463
55 rousseau 880 /* local functions */
56     static void init_driver(void);
57 rousseau 773
58    
59 rousseau 998 RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPTSTR lpcDevice)
60 rousseau 649 {
61 rousseau 770 RESPONSECODE return_value = IFD_SUCCESS;
62    
63 rousseau 773 if (! DebugInitialized)
64 rousseau 880 init_driver();
65 rousseau 773
66 rousseau 649 DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
67    
68     if (CheckLun(Lun))
69     return IFD_COMMUNICATION_ERROR;
70    
71 rousseau 892 /* Reset ATR buffer */
72 rousseau 649 CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;
73     *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';
74    
75 rousseau 892 /* Reset PowerFlags */
76 rousseau 649 CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;
77    
78     #ifdef HAVE_PTHREAD
79     pthread_mutex_lock(&ifdh_context_mutex);
80     #endif
81    
82     if (OpenPortByName(Lun, lpcDevice) != STATUS_SUCCESS)
83     {
84 rousseau 663 DEBUG_CRITICAL("failed");
85 rousseau 770 return_value = IFD_COMMUNICATION_ERROR;
86 rousseau 649 }
87    
88 rousseau 769 /* Maybe we have a special treatment for this reader */
89     ccid_open_hack(Lun);
90    
91 rousseau 649 #ifdef HAVE_PTHREAD
92     pthread_mutex_unlock(&ifdh_context_mutex);
93     #endif
94    
95 rousseau 770 return return_value;
96 rousseau 649 } /* IFDHCreateChannelByName */
97    
98    
99 rousseau 269 RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
100     {
101     /*
102     * Lun - Logical Unit Number, use this for multiple card slots or
103     * multiple readers. 0xXXXXYYYY - XXXX multiple readers, YYYY multiple
104     * slots. The resource manager will set these automatically. By
105     * default the resource manager loads a new instance of the driver so
106     * if your reader does not have more than one smartcard slot then
107     * ignore the Lun in all the functions. Future versions of PC/SC might
108     * support loading multiple readers through one instance of the driver
109     * in which XXXX would be important to implement if you want this.
110     */
111    
112     /*
113     * Channel - Channel ID. This is denoted by the following: 0x000001 -
114     * /dev/pcsc/1 0x000002 - /dev/pcsc/2 0x000003 - /dev/pcsc/3
115     *
116     * USB readers may choose to ignore this parameter and query the bus
117     * for the particular reader.
118     */
119    
120     /*
121     * This function is required to open a communications channel to the
122     * port listed by Channel. For example, the first serial reader on
123     * COM1 would link to /dev/pcsc/1 which would be a sym link to
124     * /dev/ttyS0 on some machines This is used to help with intermachine
125     * independance.
126     *
127     * Once the channel is opened the reader must be in a state in which
128     * it is possible to query IFDHICCPresence() for card status.
129     *
130     * returns:
131     *
132     * IFD_SUCCESS IFD_COMMUNICATION_ERROR
133     */
134     RESPONSECODE return_value = IFD_SUCCESS;
135    
136 rousseau 773 if (! DebugInitialized)
137 rousseau 880 init_driver();
138 rousseau 773
139 rousseau 608 DEBUG_INFO2("lun: %X", Lun);
140 rousseau 269
141     if (CheckLun(Lun))
142     return IFD_COMMUNICATION_ERROR;
143    
144 rousseau 410 /* Reset ATR buffer */
145 rousseau 269 CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;
146     *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';
147    
148 rousseau 410 /* Reset PowerFlags */
149 rousseau 269 CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;
150    
151 rousseau 563 #ifdef HAVE_PTHREAD
152 rousseau 463 pthread_mutex_lock(&ifdh_context_mutex);
153     #endif
154    
155 rousseau 410 if (OpenPort(Lun, Channel) != STATUS_SUCCESS)
156 rousseau 269 {
157 rousseau 663 DEBUG_CRITICAL("failed");
158 rousseau 269 return_value = IFD_COMMUNICATION_ERROR;
159     }
160    
161 rousseau 612 /* Maybe we have a special treatment for this reader */
162     ccid_open_hack(Lun);
163    
164 rousseau 563 #ifdef HAVE_PTHREAD
165 rousseau 463 pthread_mutex_unlock(&ifdh_context_mutex);
166     #endif
167    
168 rousseau 269 return return_value;
169     } /* IFDHCreateChannel */
170    
171    
172     RESPONSECODE IFDHCloseChannel(DWORD Lun)
173     {
174     /*
175     * This function should close the reader communication channel for the
176     * particular reader. Prior to closing the communication channel the
177     * reader should make sure the card is powered down and the terminal
178     * is also powered down.
179     *
180     * returns:
181     *
182     * IFD_SUCCESS IFD_COMMUNICATION_ERROR
183     */
184    
185 rousseau 608 DEBUG_INFO2("lun: %X", Lun);
186 rousseau 269
187     if (CheckLun(Lun))
188     return IFD_COMMUNICATION_ERROR;
189    
190     CmdPowerOff(Lun);
191 rousseau 410 /* No reader status check, if it failed, what can you do ? :) */
192 rousseau 269
193 rousseau 563 #ifdef HAVE_PTHREAD
194 rousseau 463 pthread_mutex_lock(&ifdh_context_mutex);
195     #endif
196    
197 rousseau 410 ClosePort(Lun);
198 rousseau 269
199 rousseau 563 #ifdef HAVE_PTHREAD
200 rousseau 463 pthread_mutex_unlock(&ifdh_context_mutex);
201     #endif
202    
203 rousseau 269 return IFD_SUCCESS;
204     } /* IFDHCloseChannel */
205    
206    
207     RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
208     PDWORD Length, PUCHAR Value)
209     {
210     /*
211     * This function should get the slot/card capabilities for a
212     * particular slot/card specified by Lun. Again, if you have only 1
213     * card slot and don't mind loading a new driver for each reader then
214     * ignore Lun.
215     *
216     * Tag - the tag for the information requested example: TAG_IFD_ATR -
217     * return the Atr and it's size (required). these tags are defined in
218     * ifdhandler.h
219     *
220     * Length - the length of the returned data Value - the value of the
221     * data
222     *
223     * returns:
224     *
225     * IFD_SUCCESS IFD_ERROR_TAG
226     */
227    
228 rousseau 804 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
229 rousseau 269
230     if (CheckLun(Lun))
231     return IFD_COMMUNICATION_ERROR;
232    
233     switch (Tag)
234     {
235     case TAG_IFD_ATR:
236 rousseau 804 case SCARD_ATTR_ATR_STRING:
237 rousseau 410 /* If Length is not zero, powerICC has been performed.
238     * Otherwise, return NULL pointer
239     * Buffer size is stored in *Length */
240 rousseau 804 *Length = (*Length < CcidSlots[LunToReaderIndex(Lun)].nATRLength) ?
241     *Length : CcidSlots[LunToReaderIndex(Lun)].nATRLength;
242 rousseau 269
243     if (*Length)
244     memcpy(Value, CcidSlots[LunToReaderIndex(Lun)]
245     .pcATRBuffer, *Length);
246     break;
247    
248 rousseau 563 #ifdef HAVE_PTHREAD
249 rousseau 269 case TAG_IFD_SIMULTANEOUS_ACCESS:
250     if (*Length >= 1)
251     {
252     *Length = 1;
253 rousseau 410 *Value = PCSCLITE_MAX_READERS;
254 rousseau 269 }
255     break;
256    
257 rousseau 463 case TAG_IFD_THREAD_SAFE:
258     if (*Length >= 1)
259     {
260     *Length = 1;
261     *Value = 1; /* Can talk to multiple readers at the same time */
262     }
263     break;
264 rousseau 563 #endif
265 rousseau 463
266 rousseau 269 case TAG_IFD_SLOTS_NUMBER:
267     if (*Length >= 1)
268     {
269     *Length = 1;
270     *Value = 1; /* One slot only */
271     }
272     break;
273    
274 rousseau 900 case IOCTL_SMARTCARD_VENDOR_VERIFY_PIN:
275     if (*Length >= 1)
276     {
277     *Length = 1;
278     *Value = get_ccid_descriptor(Lun) -> bPINSupport & CCID_CLASS_PIN_VERIFY;
279     }
280     break;
281    
282 rousseau 269 default:
283     return IFD_ERROR_TAG;
284     }
285 rousseau 569
286 rousseau 269 return IFD_SUCCESS;
287     } /* IFDHGetCapabilities */
288    
289    
290     RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
291 rousseau 1053 /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
292 rousseau 269 {
293     /*
294     * This function should set the slot/card capabilities for a
295     * particular slot/card specified by Lun. Again, if you have only 1
296     * card slot and don't mind loading a new driver for each reader then
297     * ignore Lun.
298     *
299     * Tag - the tag for the information needing set
300     *
301     * Length - the length of the returned data Value - the value of the
302     * data
303     *
304     * returns:
305     *
306     * IFD_SUCCESS IFD_ERROR_TAG IFD_ERROR_SET_FAILURE
307     * IFD_ERROR_VALUE_READ_ONLY
308     */
309    
310 rousseau 410 /* By default, say it worked */
311 rousseau 269
312 rousseau 804 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
313 rousseau 269
314     /* if (CheckLun(Lun))
315     return IFD_COMMUNICATION_ERROR; */
316    
317 rousseau 569 return IFD_NOT_SUPPORTED;
318 rousseau 269 } /* IFDHSetCapabilities */
319    
320    
321     RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
322     UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
323     {
324     /*
325     * This function should set the PTS of a particular card/slot using
326     * the three PTS parameters sent
327     *
328 rousseau 998 * Protocol - 0 .... 14 T=0 .... T=14
329     * Flags - Logical OR of possible values:
330     * IFD_NEGOTIATE_PTS1
331     * IFD_NEGOTIATE_PTS2
332     * IFD_NEGOTIATE_PTS3
333     * to determine which PTS values to negotiate.
334     * PTS1,PTS2,PTS3 - PTS Values.
335 rousseau 269 *
336     * returns:
337 rousseau 998 * IFD_SUCCESS
338     * IFD_ERROR_PTS_FAILURE
339     * IFD_COMMUNICATION_ERROR
340     * IFD_PROTOCOL_NOT_SUPPORTED
341 rousseau 269 */
342    
343 rousseau 998 BYTE pps[PPS_MAX_LENGTH];
344     ATR atr;
345     unsigned int len;
346     int convention;
347 rousseau 269
348 rousseau 998 /* Set ccid desc params */
349     CcidDesc *ccid_slot;
350     _ccid_descriptor *ccid_desc;
351 rousseau 269
352 rousseau 998 DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
353    
354     if (CheckLun(Lun))
355     return IFD_COMMUNICATION_ERROR;
356    
357     /* Set to zero buffer */
358     memset(pps, 0, sizeof(pps));
359     memset(&atr, 0, sizeof(atr));
360    
361     /* Get ccid params */
362     ccid_slot = get_ccid_slot(Lun);
363     ccid_desc = get_ccid_descriptor(Lun);
364    
365     /* Get ATR of the card */
366     ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
367    
368     if (SCARD_PROTOCOL_T0 == Protocol)
369     pps[1] |= ATR_PROTOCOL_TYPE_T0;
370     else
371     if (SCARD_PROTOCOL_T1 == Protocol)
372     pps[1] |= ATR_PROTOCOL_TYPE_T1;
373     else
374     return IFD_PROTOCOL_NOT_SUPPORTED;
375    
376     /* TA2 present -> specific mode */
377     if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
378     {
379     if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
380     {
381     /* wrong protocol */
382     DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
383     atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
384    
385     return IFD_PROTOCOL_NOT_SUPPORTED;
386     }
387     }
388    
389     /* TCi (i>2) indicates CRC instead of LRC */
390     if (SCARD_PROTOCOL_T1 == Protocol)
391     {
392     t1_state_t *t1 = &(ccid_slot -> t1);
393     int i;
394    
395     /* TCi (i>2) present? */
396     for (i=2; i<ATR_MAX_PROTOCOLS; i++)
397     if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
398     {
399     if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
400     {
401     DEBUG_COMM("Use LRC");
402     t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
403     }
404     else
405     if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
406     {
407     DEBUG_COMM("Use CRC");
408     t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
409     }
410     else
411     DEBUG_COMM2("Wrong value for TCi: %d",
412     atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
413    
414     /* only the first TCi (i>2) must be used */
415     break;
416     }
417     }
418    
419     /* PTS1? */
420     if (Flags & IFD_NEGOTIATE_PTS1)
421     {
422     /* just use the value passed in argument */
423     pps[1] |= 0x10; /* PTS1 presence */
424     pps[2] = PTS1;
425     }
426     else
427     {
428     /* PPS not negociated by reader, and TA1 present */
429     if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present &&
430     ! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
431     {
432     unsigned int card_baudrate;
433     unsigned int default_baudrate;
434     double f, d;
435    
436     ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
437     ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
438    
439     /* Baudrate = f x D/F */
440     card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
441     * d / f);
442    
443     default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
444     * ATR_DEFAULT_D / ATR_DEFAULT_F);
445    
446     /* if the reader is fast enough */
447     if ((card_baudrate < ccid_desc->dwMaxDataRate)
448     /* and the card does not try to lower the default speed */
449     && (card_baudrate > default_baudrate ))
450     {
451     pps[1] |= 0x10; /* PTS1 presence */
452     pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
453    
454     DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
455     }
456     }
457     }
458    
459     /* PTS2? */
460     if (Flags & IFD_NEGOTIATE_PTS2)
461     {
462     pps[1] |= 0x20; /* PTS2 presence */
463     pps[3] = PTS2;
464     }
465    
466     /* PTS3? */
467     if (Flags & IFD_NEGOTIATE_PTS3)
468     {
469     pps[1] |= 0x40; /* PTS3 presence */
470     pps[4] = PTS3;
471     }
472    
473     /* Generate PPS */
474     pps[0] = 0xFF;
475    
476     /* Automatic PPS made by the ICC? */
477     if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
478     /* TA2 absent: negociable mode */
479     && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
480     {
481     int default_protocol;
482    
483     if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
484     return IFD_PROTOCOL_NOT_SUPPORTED;
485    
486     /* if the requested protocol is not the default one
487     * or a TA1/PPS1 is present */
488     if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
489     if (PPS_Exchange(Lun, pps, &len, &pps[2]) != PPS_OK)
490     {
491     DEBUG_INFO("PPS_Exchange Failed");
492    
493     return IFD_ERROR_PTS_FAILURE;
494     }
495     }
496    
497     /* Now we must set the reader parameters */
498     ATR_GetConvention(&atr, &convention);
499    
500     /* specific mode and implicit parameters? (b5 of TA2) */
501     if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
502     && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
503     return IFD_COMMUNICATION_ERROR;
504    
505     /* T=1 */
506     if (SCARD_PROTOCOL_T1 == Protocol)
507     {
508     BYTE param[] = {
509     0x11, /* Fi/Di */
510     0x10, /* TCCKS */
511     0x00, /* GuardTime */
512     0x4D, /* BWI/BCI */
513     0x00, /* ClockStop */
514     0x20, /* IFSC */
515     0x00 /* NADValue */
516     };
517     int i;
518    
519     /* TA1 is not default */
520     if (PPS_HAS_PPS1(pps))
521     param[0] = pps[2];
522    
523     if (ATR_CONVENTION_INVERSE == convention)
524     param[1] &= 0x02;
525    
526     /* get TC1 Extra guard time */
527     if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
528     param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
529    
530     /* TBi (i>2) present? BWI/BCI */
531     for (i=2; i<ATR_MAX_PROTOCOLS; i++)
532     if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
533     {
534     DEBUG_COMM3("BWI/BCI (TB%d) present: %d", i+1,
535     atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
536     param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
537    
538     /* only the first TBi (i>2) must be used */
539     break;
540     }
541    
542 rousseau 1058 if (IFD_SUCCESS != SetParameters(Lun, 1, sizeof(param), param))
543     return IFD_COMMUNICATION_ERROR;
544 rousseau 998 }
545     else
546     /* T=0 */
547     {
548     BYTE param[] = {
549     0x11, /* Fi/Di */
550     0x00, /* TCCKS */
551     0x00, /* GuardTime */
552     0x0A, /* WaitingInteger */
553     0x00 /* ClockStop */
554     };
555    
556     /* TA1 is not default */
557     if (PPS_HAS_PPS1(pps))
558     param[0] = pps[2];
559    
560     if (ATR_CONVENTION_INVERSE == convention)
561     param[1] &= 0x02;
562    
563     /* get TC1 Extra guard time */
564     if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
565     param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
566    
567     /* TC2 WWT */
568     if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
569     param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
570    
571 rousseau 1058 if (IFD_SUCCESS != SetParameters(Lun, 0, sizeof(param), param))
572     return IFD_COMMUNICATION_ERROR;
573 rousseau 998 }
574    
575     /* set IFSC & IFSD in T=1 */
576     if (SCARD_PROTOCOL_T1 == Protocol)
577     {
578     t1_state_t *t1 = &(ccid_slot -> t1);
579     int i;
580    
581     /* TAi (i>2) present? */
582     for (i=2; i<ATR_MAX_PROTOCOLS; i++)
583     if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
584     {
585     DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
586     atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
587     t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
588     atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
589    
590     /* only the first TAi (i>2) must be used */
591     break;
592     }
593    
594     /* IFSD not negociated by the reader? */
595     if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
596     {
597     DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
598     if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
599     return IFD_COMMUNICATION_ERROR;
600     }
601     t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
602    
603     DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
604     }
605    
606     return IFD_SUCCESS;
607 rousseau 269 } /* IFDHSetProtocolParameters */
608    
609    
610     RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
611     PUCHAR Atr, PDWORD AtrLength)
612     {
613     /*
614     * This function controls the power and reset signals of the smartcard
615     * reader at the particular reader/slot specified by Lun.
616     *
617     * Action - Action to be taken on the card.
618     *
619     * IFD_POWER_UP - Power and reset the card if not done so (store the
620     * ATR and return it and it's length).
621     *
622     * IFD_POWER_DOWN - Power down the card if not done already
623     * (Atr/AtrLength should be zero'd)
624     *
625     * IFD_RESET - Perform a quick reset on the card. If the card is not
626     * powered power up the card. (Store and return the Atr/Length)
627     *
628     * Atr - Answer to Reset of the card. The driver is responsible for
629     * caching this value in case IFDHGetCapabilities is called requesting
630     * the ATR and it's length. This should not exceed MAX_ATR_SIZE.
631     *
632     * AtrLength - Length of the Atr. This should not exceed
633     * MAX_ATR_SIZE.
634     *
635     * Notes:
636     *
637     * Memory cards without an ATR should return IFD_SUCCESS on reset but
638     * the Atr should be zero'd and the length should be zero
639     *
640     * Reset errors should return zero for the AtrLength and return
641     * IFD_ERROR_POWER_ACTION.
642     *
643     * returns:
644     *
645     * IFD_SUCCESS IFD_ERROR_POWER_ACTION IFD_COMMUNICATION_ERROR
646     * IFD_NOT_SUPPORTED
647     */
648    
649 rousseau 892 unsigned int nlength;
650 rousseau 269 RESPONSECODE return_value = IFD_SUCCESS;
651     unsigned char pcbuffer[RESP_BUF_SIZE];
652    
653 rousseau 608 DEBUG_INFO2("lun: %X", Lun);
654 rousseau 269
655 rousseau 410 /* By default, assume it won't work :) */
656 rousseau 269 *AtrLength = 0;
657    
658     if (CheckLun(Lun))
659     return IFD_COMMUNICATION_ERROR;
660    
661 rousseau 766 switch (Action)
662 rousseau 269 {
663 rousseau 766 case IFD_POWER_DOWN:
664     /* Clear ATR buffer */
665     CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;
666     *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';
667 rousseau 269
668 rousseau 766 /* Memorise the request */
669     CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=
670     MASK_POWERFLAGS_PDWN;
671 rousseau 998
672 rousseau 766 /* send the command */
673     if (IFD_SUCCESS != CmdPowerOff(Lun))
674     {
675     DEBUG_CRITICAL("PowerDown failed");
676     return_value = IFD_ERROR_POWER_ACTION;
677     goto end;
678     }
679 rousseau 269
680 rousseau 998 /* clear T=1 context */
681     t1_release(&(get_ccid_slot(Lun) -> t1));
682 rousseau 840 break;
683 rousseau 616
684 rousseau 766 case IFD_POWER_UP:
685     case IFD_RESET:
686     nlength = sizeof(pcbuffer);
687     if (CmdPowerOn(Lun, &nlength, pcbuffer) != IFD_SUCCESS)
688     {
689     DEBUG_CRITICAL("PowerUp failed");
690     return_value = IFD_ERROR_POWER_ACTION;
691     goto end;
692     }
693 rousseau 269
694 rousseau 766 /* Power up successful, set state variable to memorise it */
695     CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=
696     MASK_POWERFLAGS_PUP;
697     CcidSlots[LunToReaderIndex(Lun)].bPowerFlags &=
698     ~MASK_POWERFLAGS_PDWN;
699 rousseau 269
700 rousseau 766 /* Reset is returned, even if TCK is wrong */
701     CcidSlots[LunToReaderIndex(Lun)].nATRLength = *AtrLength =
702     (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
703     memcpy(Atr, pcbuffer, *AtrLength);
704     memcpy(CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer,
705     pcbuffer, *AtrLength);
706 rousseau 616
707 rousseau 998 /* initialise T=1 context */
708     t1_init(&(get_ccid_slot(Lun) -> t1));
709 rousseau 766 break;
710    
711     default:
712     DEBUG_CRITICAL("Action not supported");
713     return_value = IFD_NOT_SUPPORTED;
714 rousseau 269 }
715     end:
716    
717     return return_value;
718     } /* IFDHPowerICC */
719    
720    
721     RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
722     PUCHAR TxBuffer, DWORD TxLength,
723 rousseau 1053 PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
724 rousseau 269 {
725     /*
726     * This function performs an APDU exchange with the card/slot
727     * specified by Lun. The driver is responsible for performing any
728     * protocol specific exchanges such as T=0/1 ... differences. Calling
729     * this function will abstract all protocol differences.
730     *
731     * SendPci Protocol - 0, 1, .... 14 Length - Not used.
732     *
733     * TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F
734     * 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU
735     * example (0x61 0x14) RxLength - Length of the received APDU. This
736     * function will be passed the size of the buffer of RxBuffer and this
737     * function is responsible for setting this to the length of the
738     * received APDU. This should be ZERO on all errors. The resource
739     * manager will take responsibility of zeroing out any temporary APDU
740     * buffers for security reasons.
741     *
742     * RecvPci Protocol - 0, 1, .... 14 Length - Not used.
743     *
744     * Notes: The driver is responsible for knowing what type of card it
745     * has. If the current slot/card contains a memory card then this
746     * command should ignore the Protocol and use the MCT style commands
747     * for support for these style cards and transmit them appropriately.
748     * If your reader does not support memory cards or you don't want to
749     * then ignore this.
750     *
751     * RxLength should be set to zero on error.
752     *
753     * returns:
754     *
755     * IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT
756     * IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED
757     */
758    
759 rousseau 611 RESPONSECODE return_value;
760 rousseau 892 unsigned int rx_length;
761 rousseau 269
762 rousseau 608 DEBUG_INFO2("lun: %X", Lun);
763 rousseau 269
764     if (CheckLun(Lun))
765     return IFD_COMMUNICATION_ERROR;
766    
767 rousseau 611 rx_length = *RxLength;
768 rousseau 616 return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, &rx_length, RxBuffer,
769     SendPci.Protocol);
770 rousseau 611 *RxLength = rx_length;
771 rousseau 269
772     return return_value;
773     } /* IFDHTransmitToICC */
774    
775    
776 rousseau 880 RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, LPCVOID TxBuffer,
777     DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)
778 rousseau 269 {
779     /*
780     * This function performs a data exchange with the reader (not the
781     * card) specified by Lun. Here XXXX will only be used. It is
782     * responsible for abstracting functionality such as PIN pads,
783     * biometrics, LCD panels, etc. You should follow the MCT, CTBCS
784     * specifications for a list of accepted commands to implement.
785     *
786     * TxBuffer - Transmit data TxLength - Length of this buffer. RxBuffer
787     * - Receive data RxLength - Length of the received data. This
788     * function will be passed the length of the buffer RxBuffer and it
789     * must set this to the length of the received data.
790     *
791     * Notes: RxLength should be zero on error.
792     */
793 rousseau 880 RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
794 rousseau 269
795 rousseau 795 DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
796 rousseau 269
797 rousseau 880 if (CheckLun(Lun) || (NULL == pdwBytesReturned) || (NULL == RxBuffer))
798     return return_value;
799 rousseau 269
800 rousseau 568 /* Set the return length to 0 to avoid problems */
801 rousseau 880 *pdwBytesReturned = 0;
802 rousseau 568
803 rousseau 880 if (IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE == dwControlCode)
804     {
805     if (FALSE == (DriverOptions & DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED))
806 rousseau 891 {
807     DEBUG_INFO("ifd exchange (Escape command) not allowed");
808 rousseau 880 return_value = IFD_COMMUNICATION_ERROR;
809 rousseau 891 }
810 rousseau 880 else
811     {
812 rousseau 892 unsigned int iBytesReturned;
813 rousseau 891
814     iBytesReturned = RxLength;
815 rousseau 880 return_value = CmdEscape(Lun, TxBuffer, TxLength, RxBuffer,
816 rousseau 891 &iBytesReturned);
817     *pdwBytesReturned = iBytesReturned;
818 rousseau 880 }
819     }
820    
821 rousseau 891 if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)
822     {
823 rousseau 892 unsigned int iBytesReturned;
824 rousseau 891
825     iBytesReturned = RxLength;
826     return_value = SecurePIN(Lun, TxBuffer, TxLength, RxBuffer,
827     &iBytesReturned);
828     *pdwBytesReturned = iBytesReturned;
829     }
830    
831 rousseau 880 return return_value;
832 rousseau 269 } /* IFDHControl */
833    
834    
835     RESPONSECODE IFDHICCPresence(DWORD Lun)
836     {
837     /*
838     * This function returns the status of the card inserted in the
839     * reader/slot specified by Lun. It will return either:
840     *
841     * returns: IFD_ICC_PRESENT IFD_ICC_NOT_PRESENT
842     * IFD_COMMUNICATION_ERROR
843     */
844    
845     unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
846     RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
847 rousseau 999 int oldLogLevel;
848 rousseau 269
849 rousseau 608 DEBUG_PERIODIC2("lun: %X", Lun);
850 rousseau 269
851     if (CheckLun(Lun))
852     return IFD_COMMUNICATION_ERROR;
853    
854 rousseau 999 /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
855     oldLogLevel = LogLevel;
856     if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
857     LogLevel &= ~DEBUG_LEVEL_COMM;
858    
859     return_value = CmdGetSlotStatus(Lun, pcbuffer);
860    
861     /* set back the old LogLevel */
862     LogLevel = oldLogLevel;
863    
864     if (return_value != IFD_SUCCESS)
865 rousseau 269 return IFD_COMMUNICATION_ERROR;
866    
867 rousseau 999 return_value = IFD_COMMUNICATION_ERROR;
868 rousseau 269 switch (pcbuffer[7]) /* bStatus */
869     {
870     case 0x00:
871     case 0x01:
872     return_value = IFD_ICC_PRESENT;
873     break;
874    
875     case 0x02:
876 rousseau 807 /* Reset ATR buffer */
877     CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;
878     *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';
879    
880     /* Reset PowerFlags */
881     CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;
882    
883 rousseau 269 return_value = IFD_ICC_NOT_PRESENT;
884     break;
885     }
886    
887     return return_value;
888     } /* IFDHICCPresence */
889    
890 rousseau 609
891 rousseau 1043 CcidDesc *get_ccid_slot(unsigned int lun)
892 rousseau 609 {
893     return &CcidSlots[LunToReaderIndex(lun)];
894     } /* get_ccid_slot */
895    
896 rousseau 673
897 rousseau 880 void init_driver(void)
898 rousseau 773 {
899     char keyValue[TOKEN_MAX_VALUE_SIZE];
900     char infofile[FILENAME_MAX];
901    
902     /* Info.plist full patch filename */
903     snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
904     PCSCLITE_HP_DROPDIR, BUNDLE);
905    
906 rousseau 880 /* Log level */
907     if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
908     {
909     /* convert from hex or dec or octal */
910     LogLevel = strtoul(keyValue, 0, 16);
911 rousseau 773
912 rousseau 880 /* print the log level used */
913     debug_msg("%s:%d:%s LogLevel: 0x%.4X", __FILE__, __LINE__, __FUNCTION__,
914     LogLevel);
915     }
916 rousseau 773
917 rousseau 880 /* Driver options */
918     if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
919     {
920     /* convert from hex or dec or octal */
921     DriverOptions = strtoul(keyValue, 0, 16);
922 rousseau 773
923 rousseau 880 /* print the log level used */
924     debug_msg("%s:%d:%s DriverOptions: 0x%.4X", __FILE__, __LINE__,
925     __FUNCTION__, DriverOptions);
926     }
927    
928 rousseau 773 DebugInitialized = TRUE;
929 rousseau 880 } /* init_driver */
930 rousseau 773

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5