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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5