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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2092 - (hide annotations) (download)
Mon Jul 3 14:00:55 2006 UTC (6 years, 10 months ago) by rousseau
File MIME type: text/plain
File size: 37002 byte(s)
CmdXfrBlockTPDU_T1(): also log the length of the reception buffer
1 rousseau 269 /*
2     commands.c: Commands sent to the card
3 rousseau 1286 Copyright (C) 2003-2004 Ludovic Rousseau
4 rousseau 269
5 rousseau 1399 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 rousseau 269
10 rousseau 1399 This library is distributed in the hope that it will be useful,
11 rousseau 269 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 rousseau 1399 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13     Lesser General Public License for more details.
14 rousseau 269
15 rousseau 1399 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 rousseau 269 */
19    
20     /*
21     * $Id$
22     */
23    
24     #include <string.h>
25 rousseau 614 #include <stdlib.h>
26 rousseau 1771 #include <pcsclite.h>
27     #include <ifdhandler.h>
28 rousseau 1857 #include <reader.h>
29 rousseau 269
30     #include "commands.h"
31 rousseau 990 #include "openct/proto-t1.h"
32 rousseau 407 #include "ccid.h"
33 rousseau 269 #include "defs.h"
34 rousseau 879 #include "ccid_ifdhandler.h"
35 rousseau 269 #include "config.h"
36     #include "debug.h"
37    
38 rousseau 1793 /* All the pinpad readers I used are more or less bogus
39     * I use code to change the user command and make the firmware happy */
40     #define BOGUS_PINPAD_FIRMWARE
41    
42 rousseau 1675 #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
43 rousseau 1857 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
44 rousseau 1675
45 rousseau 1066 /* internal functions */
46 rousseau 1106 static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
47     unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
48 rousseau 1066 unsigned char rx_buffer[]);
49    
50 rousseau 1286 static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index, unsigned int
51     tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned
52     char rx_buffer[]);
53    
54 rousseau 1106 static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
55     unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
56 rousseau 1066 unsigned char rx_buffer[]);
57    
58 rousseau 1068 static void i2dw(int value, unsigned char *buffer);
59 rousseau 1066
60 rousseau 1068
61 rousseau 407 /*****************************************************************************
62     *
63     * CmdPowerOn
64     *
65     ****************************************************************************/
66 rousseau 1106 RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
67 rousseau 1790 unsigned char buffer[], int voltage)
68 rousseau 269 {
69     unsigned char cmd[10];
70     status_t res;
71 rousseau 1566 int length, count = 1;
72     unsigned int atr_len;
73 rousseau 269 RESPONSECODE return_value = IFD_SUCCESS;
74 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
75 rousseau 269
76     /* store length of buffer[] */
77     length = *nlength;
78 rousseau 991
79     if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)
80     voltage = 0; /* automatic voltage selection */
81    
82 rousseau 269 again:
83     cmd[0] = 0x62; /* IccPowerOn */
84     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
85 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
86 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
87 rousseau 991 cmd[7] = voltage;
88 rousseau 269 cmd[8] = cmd[9] = 0; /* RFU */
89    
90 rousseau 1106 res = WritePort(reader_index, sizeof(cmd), cmd);
91 rousseau 269 if (res != STATUS_SUCCESS)
92     return IFD_COMMUNICATION_ERROR;
93    
94     /* reset available buffer size */
95     /* needed if we go back after a switch to ISO mode */
96     *nlength = length;
97    
98 rousseau 1106 res = ReadPort(reader_index, nlength, buffer);
99 rousseau 269 if (res != STATUS_SUCCESS)
100     return IFD_COMMUNICATION_ERROR;
101    
102 rousseau 407 if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
103 rousseau 269 {
104 rousseau 990 ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
105 rousseau 269
106 rousseau 1226 if (0xBB == buffer[ERROR_OFFSET] && /* Protocol error in EMV mode */
107     ((GEMPC433 == ccid_descriptor->readerID)
108     || (CHERRYXX33 == ccid_descriptor->readerID)))
109 rousseau 269 {
110 rousseau 1227 unsigned char cmd[] = {0x1F, 0x01};
111 rousseau 879 unsigned char res[1];
112 rousseau 892 unsigned int res_length = sizeof(res);
113 rousseau 879
114 rousseau 1227 if ((return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
115 rousseau 879 &res_length)) != IFD_SUCCESS)
116 rousseau 269 return return_value;
117    
118     /* avoid looping if we can't switch mode */
119     if (count--)
120     goto again;
121     else
122     DEBUG_CRITICAL("Can't set reader in ISO mode");
123     }
124    
125 rousseau 991 /* continue with 3 volts and 5 volts */
126     if (voltage > 1)
127     {
128 rousseau 1790 char *voltage_code[] = { "auto", "5V", "3V", "1.8V" };
129    
130     DEBUG_INFO3("Power up with %s failed. Try with %s.",
131     voltage_code[voltage], voltage_code[voltage-1]);
132 rousseau 991 voltage--;
133     goto again;
134     }
135    
136 rousseau 269 return IFD_COMMUNICATION_ERROR;
137     }
138    
139     /* extract the ATR */
140     atr_len = dw2i(buffer, 1); /* ATR length */
141     if (atr_len > *nlength)
142     atr_len = *nlength;
143     else
144     *nlength = atr_len;
145    
146 rousseau 1076 memmove(buffer, buffer+10, atr_len);
147 rousseau 269
148     return return_value;
149     } /* CmdPowerOn */
150    
151 rousseau 407
152     /*****************************************************************************
153     *
154 rousseau 1630 * SecurePINVerify
155 rousseau 891 *
156     ****************************************************************************/
157 rousseau 1630 RESPONSECODE SecurePINVerify(unsigned int reader_index,
158 rousseau 1800 unsigned char TxBuffer[], unsigned int TxLength,
159 rousseau 1106 unsigned char RxBuffer[], unsigned int *RxLength)
160 rousseau 891 {
161     unsigned char cmd[11+14+CMD_BUF_SIZE];
162 rousseau 1630 unsigned int a, b;
163 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
164 rousseau 1675 int old_read_timeout;
165     RESPONSECODE ret;
166 rousseau 891
167     cmd[0] = 0x69; /* Secure */
168 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
169 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
170 rousseau 891 cmd[7] = 0; /* bBWI */
171     cmd[8] = 0; /* wLevelParameter */
172     cmd[9] = 0;
173     cmd[10] = 0; /* bPINOperation: PIN Verification */
174    
175 rousseau 1670 /* 19 is the size of the PCSCv2 PIN verify structure
176 rousseau 1630 * The equivalent CCID structure is only 14-bytes long */
177 rousseau 1670 if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */
178 rousseau 1630 {
179 rousseau 1982 DEBUG_INFO3("Command too long: %d > %d", TxLength, 19+CMD_BUF_SIZE);
180 rousseau 1630 *RxLength = 0;
181 rousseau 1301 return IFD_NOT_SUPPORTED;
182 rousseau 1630 }
183 rousseau 1301
184 rousseau 1670 if (TxLength < 19+4 /* 4 = APDU size */) /* command too short? */
185 rousseau 1630 {
186 rousseau 1670 DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4);
187 rousseau 1630 *RxLength = 0;
188     return IFD_NOT_SUPPORTED;
189     }
190 rousseau 1299
191 rousseau 1670 if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */
192 rousseau 1630 {
193 rousseau 1984 DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 15) + 19, TxLength);
194 rousseau 1630 *RxLength = 0;
195     return IFD_NOT_SUPPORTED;
196     }
197    
198 rousseau 1986 /* make sure bEntryValidationCondition is valid
199     * The Cherry XX44 reader crashes with a wrong value */
200     if ((0x00 == TxBuffer[7]) || (TxBuffer[7] > 0x07))
201     {
202     DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
203     TxBuffer[7]);
204     TxBuffer[7] = 0x02;
205     }
206    
207 rousseau 1800 #ifdef BOGUS_PINPAD_FIRMWARE
208     /* bug circumvention for the GemPC Pinpad */
209     if (GEMPCPINPAD == ccid_descriptor->readerID)
210     {
211     /* the firmware reject the cases: 00h No string and FFh default
212     * CCID message. The only value supported is 01h (display 1 message) */
213     if (0x01 != TxBuffer[8])
214     {
215     DEBUG_INFO2("Correct bNumberMessage for GemPC Pinpad (was %d)",
216     TxBuffer[8]);
217     TxBuffer[8] = 0x01;
218     }
219     }
220     #endif
221    
222 rousseau 1859 /* T=1 Protocol Management for a TPDU reader */
223     if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
224     && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
225     {
226     ct_buf_t sbuf;
227     unsigned char sdata[T1_BUFFER_SIZE];
228    
229     /* Initialize send buffer with the APDU */
230     ct_buf_set(&sbuf,
231     (void *)(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, abData)),
232     TxLength - offsetof(PIN_VERIFY_STRUCTURE, abData));
233    
234     /* Create T=1 block */
235     ret = t1_build(&((get_ccid_slot(reader_index))->t1),
236     sdata, 0, T1_I_BLOCK, &sbuf, NULL);
237    
238     /* Increment the sequence numbers */
239     get_ccid_slot(reader_index)->t1.ns ^= 1;
240     get_ccid_slot(reader_index)->t1.nr ^= 1;
241    
242     /* Copy the generated T=1 block prologue into the teoprologue
243     * of the CCID command */
244     memcpy(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, bTeoPrologue),
245     sdata, 3);
246     }
247    
248 rousseau 1630 /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
249     for (a = 11, b = 0; b < TxLength; b++)
250     {
251     if (1 == b) /* bTimeOut2 field */
252     /* Ignore the second timeout as there's nothing we can do with
253     * it currently */
254     continue;
255    
256 rousseau 1670 if ((b >= 15) && (b <= 18)) /* ulDataLength field (4 bytes) */
257 rousseau 1630 /* the ulDataLength field is not present in the CCID frame
258     * so do not copy */
259     continue;
260    
261     /* copy the CCID block 'verbatim' */
262     cmd[a] = TxBuffer[b];
263     a++;
264     }
265    
266 rousseau 1310 /* SPR532 and Case 1 APDU */
267 rousseau 1630 if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
268 rousseau 1310 {
269     RESPONSECODE return_value;
270 rousseau 1630 unsigned char cmd[] = { 0x80, 0x02, 0x00 };
271 rousseau 1310 unsigned char res[1];
272     unsigned int res_length = sizeof(res);
273    
274     /* the SPR532 will append the PIN code without any padding */
275     return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
276     &res_length);
277     if (return_value != IFD_SUCCESS)
278     {
279     ccid_error(res[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);
280     return return_value;
281     }
282     }
283    
284 rousseau 1630 i2dw(a - 10, cmd + 1); /* CCID message length */
285    
286 rousseau 1675 old_read_timeout = ccid_descriptor -> readTimeout;
287     ccid_descriptor -> readTimeout = max(30, TxBuffer[0]); /* at least 30 seconds */
288    
289 rousseau 1630 if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
290 rousseau 1747 {
291     *RxLength = 0;
292 rousseau 891 return IFD_COMMUNICATION_ERROR;
293 rousseau 1747 }
294 rousseau 891
295 rousseau 2091 ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
296 rousseau 1675
297 rousseau 1857 /* T=1 Protocol Management for a TPDU reader */
298 rousseau 1860 if ((IFD_SUCCESS == ret)
299     && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
300 rousseau 1857 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
301     {
302 rousseau 1860 /* timeout and cancel cases are faked by CCID_Receive() */
303     if (2 == *RxLength)
304     {
305     /* Decrement the sequence numbers since no TPDU was sent */
306     get_ccid_slot(reader_index)->t1.ns ^= 1;
307     get_ccid_slot(reader_index)->t1.nr ^= 1;
308     }
309     else
310     {
311     /* get only the T=1 data */
312     /* FIXME: manage T=1 error blocks */
313     memmove(RxBuffer, RxBuffer+3, *RxLength -4);
314     *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
315     }
316 rousseau 1857 }
317    
318 rousseau 1675 ccid_descriptor -> readTimeout = old_read_timeout;
319     return ret;
320 rousseau 1630 } /* SecurePINVerify */
321 rousseau 891
322    
323     /*****************************************************************************
324     *
325 rousseau 1630 * SecurePINModify
326     *
327     ****************************************************************************/
328     RESPONSECODE SecurePINModify(unsigned int reader_index,
329 rousseau 1793 unsigned char TxBuffer[], unsigned int TxLength,
330 rousseau 1630 unsigned char RxBuffer[], unsigned int *RxLength)
331     {
332     unsigned char cmd[11+19+CMD_BUF_SIZE];
333     unsigned int a, b;
334     _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
335 rousseau 1704 int old_read_timeout;
336     RESPONSECODE ret;
337 rousseau 1630
338     cmd[0] = 0x69; /* Secure */
339     cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
340     cmd[6] = (*ccid_descriptor->pbSeq)++;
341     cmd[7] = 0; /* bBWI */
342     cmd[8] = 0; /* wLevelParameter */
343     cmd[9] = 0;
344     cmd[10] = 1; /* bPINOperation: PIN Modification */
345    
346 rousseau 1670 /* 24 is the size of the PCSC PIN modify structure
347 rousseau 1630 * The equivalent CCID structure is only 18 or 19-bytes long */
348 rousseau 1983 if (TxLength > 24+CMD_BUF_SIZE) /* command too large? */
349 rousseau 1746 {
350 rousseau 1983 DEBUG_INFO3("Command too long: %d > %d", TxLength, 24+CMD_BUF_SIZE);
351 rousseau 1746 *RxLength = 0;
352 rousseau 1630 return IFD_NOT_SUPPORTED;
353 rousseau 1746 }
354 rousseau 1630
355 rousseau 1983 if (TxLength < 24+4 /* 4 = APDU size */) /* command too short? */
356     {
357     DEBUG_INFO3("Command too short: %d < %d", TxLength, 24+4);
358     *RxLength = 0;
359     return IFD_NOT_SUPPORTED;
360     }
361    
362     if (dw2i(TxBuffer, 20) + 24 != TxLength) /* ulDataLength field coherency */
363     {
364     DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 20) + 24, TxLength);
365     *RxLength = 0;
366     return IFD_NOT_SUPPORTED;
367     }
368    
369 rousseau 1630 /* Make sure in the beginning if bNumberMessage is valid or not */
370     if (TxBuffer[11] > 3)
371 rousseau 1746 {
372 rousseau 1983 DEBUG_INFO2("Wrong bNumberMessage: %d", TxBuffer[11]);
373 rousseau 1746 *RxLength = 0;
374 rousseau 1630 return IFD_NOT_SUPPORTED;
375 rousseau 1746 }
376 rousseau 1630
377 rousseau 1986 /* Make sure bEntryValidationCondition is valid
378     * The Cherry XX44 reader crashes with a wrong value */
379     if ((0x00 == TxBuffer[10]) || (TxBuffer[10] > 0x07))
380     {
381     DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
382     TxBuffer[10]);
383     TxBuffer[10] = 0x02;
384     }
385    
386 rousseau 1793 #ifdef BOGUS_PINPAD_FIRMWARE
387     /* some firmwares are buggy so we try to "correct" the frame */
388     /*
389     * SPR 532 and Cherry ST 2000C has no display but requires _all_
390     * bMsgIndex fields with bNumberMessage set to 0.
391     */
392     if ((SPR532 == ccid_descriptor->readerID)
393     || (CHERRYST2000 == ccid_descriptor->readerID))
394     {
395     TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
396     all bMsgIndex123 are filled */
397     TxBuffer[14] = TxBuffer[15] = TxBuffer[16] = 0; /* bMsgIndex123 */
398     }
399 rousseau 1794
400 rousseau 1981 /* the bug is a bit different than for the Cherry ST 2000C
401     * with bNumberMessages < 3 the command seems to be accepted
402     * and the card sends 6B 80 */
403     if (CHERRYXX44 == ccid_descriptor->readerID)
404     {
405     TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
406     all bMsgIndex123 are filled */
407     }
408    
409 rousseau 1794 /* bug circumvention for the GemPC Pinpad */
410     if (GEMPCPINPAD == ccid_descriptor->readerID)
411     {
412     /* The reader does not support, and actively reject, "max size reached"
413     * and "timeout occured" validation conditions */
414     if (0x02 != TxBuffer[10])
415     {
416     DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
417     TxBuffer[10]);
418     TxBuffer[10] = 0x02; /* validation key pressed */
419     }
420    
421     /* the reader does not support any other value than 3 for the number
422     * of messages */
423     if (0x03 != TxBuffer[11])
424     {
425     DEBUG_INFO2("Correct bNumberMessages for GemPC Pinpad (was %d)",
426     TxBuffer[11]);
427     TxBuffer[11] = 0x03; /* 3 messages */
428     }
429     }
430 rousseau 1793 #endif
431    
432 rousseau 1858 /* T=1 Protocol Management for a TPDU reader */
433     if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
434     && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
435     {
436     ct_buf_t sbuf;
437     unsigned char sdata[T1_BUFFER_SIZE];
438    
439     /* Initialize send buffer with the APDU */
440     ct_buf_set(&sbuf,
441     (void *)(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, abData)),
442     TxLength - offsetof(PIN_MODIFY_STRUCTURE, abData));
443    
444     /* Create T=1 block */
445     ret = t1_build(&((get_ccid_slot(reader_index))->t1),
446     sdata, 0, T1_I_BLOCK, &sbuf, NULL);
447    
448     /* Increment the sequence numbers */
449     get_ccid_slot(reader_index)->t1.ns ^= 1;
450     get_ccid_slot(reader_index)->t1.nr ^= 1;
451    
452     /* Copy the generated T=1 block prologue into the teoprologue
453     * of the CCID command */
454     memcpy(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, bTeoPrologue),
455     sdata, 3);
456     }
457    
458 rousseau 1630 /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
459    
460     /* Do adjustments as needed - CCID spec is not exact with some
461     * details in the format of the structure, per-reader adaptions
462     * might be needed.
463     */
464     for (a = 11, b = 0; b < TxLength; b++)
465     {
466     if (1 == b) /* bTimeOut2 */
467     /* Ignore the second timeout as there's nothing we can do with it
468     * currently */
469     continue;
470    
471 rousseau 1701 if (15 == b) /* bMsgIndex2 */
472     {
473     /* in CCID the bMsgIndex2 is present only if bNumberMessage != 0 */
474     if (0 == TxBuffer[11])
475     continue;
476     }
477    
478 rousseau 1630 if (16 == b) /* bMsgIndex3 */
479     {
480     /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
481     if (TxBuffer[11] < 3)
482     continue;
483     }
484    
485 rousseau 1700 if ((b >= 20) && (b <= 23)) /* ulDataLength field (4 bytes) */
486     /* the ulDataLength field is not present in the CCID frame
487     * so do not copy */
488     continue;
489    
490 rousseau 1630 /* copy to the CCID block 'verbatim' */
491     cmd[a] = TxBuffer[b];
492     a++;
493     }
494    
495 rousseau 1793 #ifdef BOGUS_PINPAD_FIRMWARE
496     if ((SPR532 == ccid_descriptor->readerID)
497     || (CHERRYST2000 == ccid_descriptor->readerID))
498     {
499     cmd[21] = 0x00; /* set bNumberMessages to 0 */
500     }
501     #endif
502    
503 rousseau 1630 /* We know the size of the CCID message now */
504     i2dw(a - 10, cmd + 1); /* command length (includes bPINOperation) */
505    
506 rousseau 1704 old_read_timeout = ccid_descriptor -> readTimeout;
507     ccid_descriptor -> readTimeout = max(30, TxBuffer[0]); /* at least 30 seconds */
508    
509 rousseau 1630 if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
510 rousseau 1747 {
511     *RxLength = 0;
512 rousseau 1630 return IFD_COMMUNICATION_ERROR;
513 rousseau 1747 }
514 rousseau 1630
515 rousseau 2091 ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
516 rousseau 1704
517 rousseau 1858 /* T=1 Protocol Management for a TPDU reader */
518 rousseau 1860 if ((IFD_SUCCESS == ret)
519     && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
520 rousseau 1858 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
521     {
522 rousseau 1860 /* timeout and cancel cases are faked by CCID_Receive() */
523     if (2 == *RxLength)
524     {
525     /* Decrement the sequence numbers since no TPDU was sent */
526     get_ccid_slot(reader_index)->t1.ns ^= 1;
527     get_ccid_slot(reader_index)->t1.nr ^= 1;
528     }
529     else
530     {
531     /* get only the T=1 data */
532     /* FIXME: manage T=1 error blocks */
533     memmove(RxBuffer, RxBuffer+3, *RxLength -4);
534     *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
535     }
536 rousseau 1858 }
537    
538 rousseau 1704 ccid_descriptor -> readTimeout = old_read_timeout;
539     return ret;
540 rousseau 1630 } /* SecurePINModify */
541    
542    
543     /*****************************************************************************
544     *
545 rousseau 407 * Escape
546     *
547     ****************************************************************************/
548 rousseau 1106 RESPONSECODE CmdEscape(unsigned int reader_index,
549     const unsigned char TxBuffer[], unsigned int TxLength,
550     unsigned char RxBuffer[], unsigned int *RxLength)
551 rousseau 269 {
552 rousseau 879 unsigned char *cmd_in, *cmd_out;
553 rousseau 269 status_t res;
554 rousseau 892 unsigned int length_in, length_out;
555 rousseau 269 RESPONSECODE return_value = IFD_SUCCESS;
556 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
557 rousseau 269
558 rousseau 1492 again:
559 rousseau 879 /* allocate buffers */
560     length_in = 10 + TxLength;
561     if (NULL == (cmd_in = malloc(length_in)))
562     return IFD_COMMUNICATION_ERROR;
563 rousseau 269
564 rousseau 879 length_out = 10 + *RxLength;
565     if (NULL == (cmd_out = malloc(length_out)))
566 rousseau 269 {
567 rousseau 879 free(cmd_in);
568     return IFD_COMMUNICATION_ERROR;
569     }
570 rousseau 269
571 rousseau 879 cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
572     i2dw(length_in - 10, cmd_in+1); /* dwLength */
573 rousseau 1092 cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
574 rousseau 1150 cmd_in[6] = (*ccid_descriptor->pbSeq)++;
575 rousseau 879 cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
576 rousseau 407
577 rousseau 879 /* copy the command */
578     memcpy(&cmd_in[10], TxBuffer, TxLength);
579 rousseau 269
580 rousseau 1106 res = WritePort(reader_index, length_in, cmd_in);
581 rousseau 879 free(cmd_in);
582 rousseau 269 if (res != STATUS_SUCCESS)
583 rousseau 879 {
584     free(cmd_out);
585 rousseau 269 return IFD_COMMUNICATION_ERROR;
586 rousseau 879 }
587 rousseau 269
588 rousseau 1106 res = ReadPort(reader_index, &length_out, cmd_out);
589 rousseau 1492
590     /* replay the command if NAK
591     * This (generally) happens only for the first command sent to the reader
592     * with the serial protocol so it is not really needed for all the other
593     * ReadPort() calls */
594     if (STATUS_COMM_NAK == res)
595     {
596     free(cmd_out);
597     goto again;
598     }
599    
600 rousseau 269 if (res != STATUS_SUCCESS)
601 rousseau 879 {
602     free(cmd_out);
603 rousseau 269 return IFD_COMMUNICATION_ERROR;
604 rousseau 879 }
605 rousseau 269
606 rousseau 879 if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)
607 rousseau 269 {
608 rousseau 990 ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
609 rousseau 269 return_value = IFD_COMMUNICATION_ERROR;
610     }
611    
612 rousseau 879 /* copy the response */
613     length_out = dw2i(cmd_out, 1);
614     if (length_out > *RxLength)
615     length_out = *RxLength;
616     *RxLength = length_out;
617     memcpy(RxBuffer, &cmd_out[10], length_out);
618    
619     free(cmd_out);
620    
621 rousseau 269 return return_value;
622     } /* Escape */
623    
624 rousseau 407
625     /*****************************************************************************
626     *
627     * CmdPowerOff
628     *
629     ****************************************************************************/
630 rousseau 1106 RESPONSECODE CmdPowerOff(unsigned int reader_index)
631 rousseau 269 {
632     unsigned char cmd[10];
633     status_t res;
634 rousseau 892 unsigned int length;
635 rousseau 269 RESPONSECODE return_value = IFD_SUCCESS;
636 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
637 rousseau 269
638     cmd[0] = 0x63; /* IccPowerOff */
639     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
640 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
641 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
642 rousseau 269 cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
643    
644 rousseau 1106 res = WritePort(reader_index, sizeof(cmd), cmd);
645 rousseau 269 if (res != STATUS_SUCCESS)
646     return IFD_COMMUNICATION_ERROR;
647    
648     length = sizeof(cmd);
649 rousseau 1106 res = ReadPort(reader_index, &length, cmd);
650 rousseau 269 if (res != STATUS_SUCCESS)
651     return IFD_COMMUNICATION_ERROR;
652    
653 rousseau 407 if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
654 rousseau 269 {
655 rousseau 990 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
656 rousseau 269 return_value = IFD_COMMUNICATION_ERROR;
657     }
658    
659     return return_value;
660     } /* CmdPowerOff */
661    
662 rousseau 407
663     /*****************************************************************************
664     *
665     * CmdGetSlotStatus
666     *
667     ****************************************************************************/
668 rousseau 1106 RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
669 rousseau 269 {
670     unsigned char cmd[10];
671     status_t res;
672 rousseau 892 unsigned int length;
673 rousseau 269 RESPONSECODE return_value = IFD_SUCCESS;
674 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
675 rousseau 269
676     cmd[0] = 0x65; /* GetSlotStatus */
677     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
678 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
679 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
680 rousseau 269 cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
681    
682 rousseau 1106 res = WritePort(reader_index, sizeof(cmd), cmd);
683 rousseau 269 if (res != STATUS_SUCCESS)
684     return IFD_COMMUNICATION_ERROR;
685    
686     length = SIZE_GET_SLOT_STATUS;
687 rousseau 1106 res = ReadPort(reader_index, &length, buffer);
688 rousseau 269 if (res != STATUS_SUCCESS)
689     return IFD_COMMUNICATION_ERROR;
690    
691 rousseau 407 if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
692 rousseau 269 {
693 rousseau 990 ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
694 rousseau 1257
695     /* card absent or mute is not an communication error */
696     if (buffer[ERROR_OFFSET] != 0xFE)
697     return_value = IFD_COMMUNICATION_ERROR;
698 rousseau 269 }
699    
700     return return_value;
701     } /* CmdGetSlotStatus */
702    
703 rousseau 407
704     /*****************************************************************************
705     *
706     * CmdXfrBlock
707     *
708     ****************************************************************************/
709 rousseau 1106 RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
710 rousseau 892 unsigned char tx_buffer[], unsigned int *rx_length,
711     unsigned char rx_buffer[], int protocol)
712 rousseau 269 {
713 rousseau 407 RESPONSECODE return_value = IFD_SUCCESS;
714 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
715 rousseau 407
716     /* APDU or TPDU? */
717     switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)
718     {
719     case CCID_CLASS_TPDU:
720 rousseau 614 if (protocol == T_0)
721 rousseau 1106 return_value = CmdXfrBlockTPDU_T0(reader_index,
722     tx_length, tx_buffer, rx_length, rx_buffer);
723 rousseau 614 else
724     if (protocol == T_1)
725 rousseau 1106 return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
726 rousseau 614 tx_buffer, rx_length, rx_buffer);
727     else
728     return_value = IFD_PROTOCOL_NOT_SUPPORTED;
729 rousseau 407 break;
730    
731     case CCID_CLASS_SHORT_APDU:
732     case CCID_CLASS_EXTENDED_APDU:
733     /* We only support extended APDU if the reader can support the
734     * command length. See test above */
735 rousseau 1106 return_value = CmdXfrBlockTPDU_T0(reader_index,
736     tx_length, tx_buffer, rx_length, rx_buffer);
737 rousseau 407 break;
738    
739 rousseau 1286 case CCID_CLASS_CHARACTER:
740     if (protocol == T_0)
741     return_value = CmdXfrBlockCHAR_T0(reader_index, tx_length,
742     tx_buffer, rx_length, rx_buffer);
743     else
744     if (protocol == T_1)
745     return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
746     tx_buffer, rx_length, rx_buffer);
747     else
748     return_value = IFD_PROTOCOL_NOT_SUPPORTED;
749     break;
750    
751 rousseau 407 default:
752 rousseau 614 *rx_length = 0;
753 rousseau 407 return_value = IFD_COMMUNICATION_ERROR;
754     }
755    
756     clean_up_and_return:
757     return return_value;
758     } /* CmdXfrBlock */
759    
760    
761     /*****************************************************************************
762     *
763 rousseau 613 * CCID_Transmit
764 rousseau 407 *
765     ****************************************************************************/
766 rousseau 1106 RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
767 rousseau 1286 const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
768 rousseau 407 {
769 rousseau 269 unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
770 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
771 rousseau 269
772 rousseau 613 cmd[0] = 0x6F; /* XfrBlock */
773 rousseau 269 i2dw(tx_length, cmd+1); /* APDU length */
774 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
775 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
776 rousseau 992 cmd[7] = bBWI; /* extend block waiting timeout */
777 rousseau 1677 cmd[8] = rx_length & 0xFF; /* Expected length, in character mode only */
778 rousseau 1286 cmd[9] = (rx_length >> 8) & 0xFF;
779 rousseau 1301
780     /* check that the command is not too large */
781     if (tx_length > CMD_BUF_SIZE)
782 rousseau 2087 {
783     DEBUG_CRITICAL2("TX Length too big: %d", tx_length);
784 rousseau 1301 return IFD_NOT_SUPPORTED;
785 rousseau 2087 }
786 rousseau 1301
787 rousseau 269 memcpy(cmd+10, tx_buffer, tx_length);
788    
789 rousseau 1106 if (WritePort(reader_index, 10+tx_length, cmd) != STATUS_SUCCESS)
790 rousseau 269 return IFD_COMMUNICATION_ERROR;
791    
792 rousseau 613 return IFD_SUCCESS;
793     } /* CCID_Transmit */
794    
795    
796     /*****************************************************************************
797     *
798     * CCID_Receive
799     *
800     ****************************************************************************/
801 rousseau 1106 RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
802 rousseau 2090 unsigned char rx_buffer[], unsigned char *chain_parameter)
803 rousseau 613 {
804     unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
805 rousseau 892 unsigned int length;
806 rousseau 613
807 rousseau 407 time_request:
808 rousseau 269 length = sizeof(cmd);
809 rousseau 1106 if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
810 rousseau 905 {
811     *rx_length = 0;
812 rousseau 269 return IFD_COMMUNICATION_ERROR;
813 rousseau 905 }
814 rousseau 269
815 rousseau 407 if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
816 rousseau 269 {
817 rousseau 990 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
818 rousseau 1630 switch (cmd[ERROR_OFFSET])
819     {
820     case 0xEF: /* cancel */
821     if (*rx_length < 2)
822     return IFD_COMMUNICATION_ERROR;
823     rx_buffer[0]= 0x64;
824     rx_buffer[1]= 0x01;
825     *rx_length = 2;
826     return IFD_SUCCESS;
827    
828     case 0xF0: /* timeout */
829     if (*rx_length < 2)
830     return IFD_COMMUNICATION_ERROR;
831     rx_buffer[0]= 0x64;
832     rx_buffer[1]= 0x00;
833     *rx_length = 2;
834     return IFD_SUCCESS;
835    
836     case 0xFD: /* Parity error during exchange */
837     *rx_length = 0; /* nothing received */
838     return IFD_PARITY_ERROR;
839    
840     default:
841     *rx_length = 0; /* nothing received */
842     return IFD_COMMUNICATION_ERROR;
843     }
844 rousseau 269 }
845    
846 rousseau 407 if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
847     {
848 rousseau 1600 DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);
849 rousseau 407 goto time_request;
850     }
851    
852 rousseau 269 length = dw2i(cmd, 1);
853 rousseau 2086 if (length <= *rx_length)
854 rousseau 269 *rx_length = length;
855     else
856 rousseau 2086 {
857     DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);
858 rousseau 269 length = *rx_length;
859 rousseau 2086 }
860 rousseau 269 memcpy(rx_buffer, cmd+10, length);
861    
862 rousseau 658 return IFD_SUCCESS;
863 rousseau 613 } /* CCID_Receive */
864 rousseau 269
865 rousseau 407
866     /*****************************************************************************
867     *
868 rousseau 614 * CmdXfrBlockTPDU_T0
869 rousseau 407 *
870     ****************************************************************************/
871 rousseau 1106 static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
872     unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
873 rousseau 892 unsigned char rx_buffer[])
874 rousseau 407 {
875     RESPONSECODE return_value = IFD_SUCCESS;
876 rousseau 2088 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
877 rousseau 407
878 rousseau 614 DEBUG_COMM2("T=0: %d bytes", tx_length);
879 rousseau 407
880 rousseau 2088 /* command length too big for CCID reader? */
881     if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
882     {
883     DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
884     tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
885     return IFD_COMMUNICATION_ERROR;
886     }
887    
888     /* command length too big for CCID driver? */
889     if (tx_length > CMD_BUF_SIZE)
890     {
891     DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
892     tx_length, CMD_BUF_SIZE);
893     return IFD_COMMUNICATION_ERROR;
894     }
895    
896 rousseau 1286 return_value = CCID_Transmit(reader_index, tx_length, tx_buffer, 0, 0);
897 rousseau 613 if (return_value != IFD_SUCCESS)
898     return return_value;
899 rousseau 1286
900 rousseau 2091 return CCID_Receive(reader_index, rx_length, rx_buffer, NULL);
901 rousseau 614 } /* CmdXfrBlockTPDU_T0 */
902 rousseau 407
903    
904     /*****************************************************************************
905     *
906 rousseau 1286 * T0CmdParsing
907     *
908     ****************************************************************************/
909     static RESPONSECODE T0CmdParsing(unsigned char *cmd, unsigned int cmd_len,
910     unsigned int *exp_len)
911     {
912     *exp_len = 0;
913    
914     /* Ref: 7816-4 Annex A */
915     switch (cmd_len)
916     {
917     case 4: /* Case 1 */
918     *exp_len = 2; /* SW1 and SW2 only */
919     break;
920    
921     case 5: /* Case 2 */
922     if (cmd[4] != 0)
923     *exp_len = cmd[4] + 2;
924     else
925     *exp_len = 256 + 2;
926     break;
927    
928     default: /* Case 3 */
929     if (cmd_len > 5 && cmd_len == (unsigned int)(cmd[4] + 5))
930     *exp_len = 2; /* SW1 and SW2 only */
931     else
932     return IFD_COMMUNICATION_ERROR; /* situation not supported */
933     break;
934     }
935    
936     return IFD_SUCCESS;
937     } /* T0CmdParsing */
938    
939    
940     /*****************************************************************************
941     *
942     * T0ProcACK
943     *
944     ****************************************************************************/
945     static RESPONSECODE T0ProcACK(unsigned int reader_index,
946     unsigned char **snd_buf, unsigned int *snd_len,
947     unsigned char **rcv_buf, unsigned int *rcv_len,
948     unsigned char **in_buf, unsigned int *in_len,
949     unsigned int proc_len, int is_rcv)
950     {
951     RESPONSECODE return_value;
952     unsigned int remain_len;
953     unsigned char tmp_buf[512];
954     unsigned int ret_len;
955    
956     DEBUG_COMM2("Enter, is_rcv = %d", is_rcv);
957    
958     if (is_rcv == 1)
959     { /* Receiving mode */
960     if (*in_len > 0)
961     { /* There are still available data in our buffer */
962     if (*in_len >= proc_len)
963     {
964     /* We only need to get the data from our buffer */
965     memcpy(*rcv_buf, *in_buf, proc_len);
966     *rcv_buf += proc_len;
967     *in_buf += proc_len;
968     *rcv_len += proc_len;
969     *in_len -= proc_len;
970    
971     return IFD_SUCCESS;
972     }
973     else
974     {
975     /* Move all data in the input buffer to the reply buffer */
976     remain_len = proc_len - *in_len;
977     memcpy(*rcv_buf, *in_buf, *in_len);
978     *rcv_buf += *in_len;
979     *in_buf += *in_len;
980     *rcv_len += *in_len;
981     *in_len = 0;
982     }
983     }
984     else
985     /* There is no data in our tmp_buf,
986     * we have to read all data we needed */
987     remain_len = proc_len;
988    
989     /* Read the expected data from the smartcard */
990     if (*in_len != 0)
991     {
992     DEBUG_CRITICAL("*in_len != 0");
993     return IFD_COMMUNICATION_ERROR;
994     }
995    
996     memset(tmp_buf, 0, sizeof(tmp_buf));
997    
998     ret_len = remain_len;
999     return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1000     if (return_value != IFD_SUCCESS)
1001     return return_value;
1002    
1003 rousseau 2091 return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1004 rousseau 1286 if (return_value != IFD_SUCCESS)
1005     return return_value;
1006    
1007     memcpy(*rcv_buf, tmp_buf, remain_len);
1008     *rcv_buf += remain_len, *rcv_len += remain_len;
1009    
1010     /* If ret_len != remain_len, our logic is erroneous */
1011     if (ret_len != remain_len)
1012     {
1013     DEBUG_CRITICAL("ret_len != remain_len");
1014     return IFD_COMMUNICATION_ERROR;
1015     }
1016     }
1017     else
1018     { /* Sending mode */
1019    
1020     return_value = CCID_Transmit(reader_index, proc_len, *snd_buf, 1, 0);
1021     if (return_value != IFD_SUCCESS)
1022     return return_value;
1023    
1024     *snd_len -= proc_len;
1025     *snd_buf += proc_len;
1026     }
1027    
1028     DEBUG_COMM("Exit");
1029    
1030     return IFD_SUCCESS;
1031     } /* T0ProcACK */
1032    
1033    
1034     /*****************************************************************************
1035     *
1036     * T0ProcSW1
1037     *
1038     ****************************************************************************/
1039     static RESPONSECODE T0ProcSW1(unsigned int reader_index,
1040     unsigned char *rcv_buf, unsigned int *rcv_len,
1041     unsigned char *in_buf, unsigned int in_len)
1042     {
1043     RESPONSECODE return_value = IFD_SUCCESS;
1044     UCHAR tmp_buf[512];
1045     unsigned char *rcv_buf_tmp = rcv_buf;
1046     const unsigned int rcv_len_tmp = *rcv_len;
1047     unsigned char sw1, sw2;
1048    
1049     /* store the SW1 */
1050     sw1 = *rcv_buf = *in_buf;
1051     rcv_buf++;
1052     in_buf++;
1053     in_len--;
1054     (*rcv_len)++;
1055    
1056     /* store the SW2 */
1057     if (0 == in_len)
1058     {
1059     return_value = CCID_Transmit(reader_index, 0, rcv_buf, 1, 0);
1060     if (return_value != IFD_SUCCESS)
1061     return return_value;
1062    
1063     in_len = 1;
1064    
1065 rousseau 2091 return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1066 rousseau 1286 if (return_value != IFD_SUCCESS)
1067     return return_value;
1068    
1069     in_buf = tmp_buf;
1070     }
1071     sw2 = *rcv_buf = *in_buf;
1072     rcv_buf++;
1073     in_buf++;
1074     in_len--;
1075     (*rcv_len)++;
1076    
1077     if (return_value != IFD_SUCCESS)
1078     {
1079     rcv_buf_tmp[0] = rcv_buf_tmp[1] = 0;
1080     *rcv_len = rcv_len_tmp;
1081     }
1082    
1083     DEBUG_COMM3("Exit: SW=%02X %02X", sw1, sw2);
1084    
1085     return return_value;
1086     } /* T0ProcSW1 */
1087    
1088    
1089     /*****************************************************************************
1090     *
1091     * CmdXfrBlockCHAR_T0
1092     *
1093     ****************************************************************************/
1094     static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index,
1095     unsigned int snd_len, unsigned char snd_buf[], unsigned int *rcv_len,
1096     unsigned char rcv_buf[])
1097     {
1098     int is_rcv;
1099 rousseau 1311 unsigned char cmd[5];
1100 rousseau 1286 unsigned char tmp_buf[512];
1101     unsigned int exp_len, in_len;
1102     unsigned char ins, *in_buf;
1103     RESPONSECODE return_value = IFD_SUCCESS;
1104    
1105     DEBUG_COMM2("T=0: %d bytes", snd_len);
1106    
1107     in_buf = tmp_buf;
1108     in_len = 0;
1109     *rcv_len = 0;
1110    
1111     return_value = T0CmdParsing(snd_buf, snd_len, &exp_len);
1112     if (return_value != IFD_SUCCESS)
1113     {
1114     DEBUG_CRITICAL("T0CmdParsing failed");
1115     return IFD_COMMUNICATION_ERROR;
1116     }
1117    
1118     if (snd_len == 5 || snd_len == 4)
1119     is_rcv = 1;
1120     else
1121     is_rcv = 0;
1122    
1123     /* Command to send to the smart card (must be 5 bytes, from 7816 p.15) */
1124     memset(cmd, 0, sizeof(cmd));
1125     if (snd_len == 4)
1126     {
1127     memcpy(cmd, snd_buf, 4);
1128     snd_buf += 4;
1129     snd_len -= 4;
1130     }
1131     else
1132     {
1133     memcpy(cmd, snd_buf, 5);
1134     snd_buf += 5;
1135     snd_len -= 5;
1136     }
1137    
1138     /* Make sure this is a valid command by checking the INS field */
1139     ins = cmd[1];
1140     if ((ins & 0xF0) == 0x60 || /* 7816-3 8.3.2 */
1141     (ins & 0xF0) == 0x90)
1142     {
1143     DEBUG_CRITICAL2("fatal: INS (0x%02X) = 0x6X or 0x9X", ins);
1144     return IFD_COMMUNICATION_ERROR;
1145     }
1146    
1147     return_value = CCID_Transmit(reader_index, 5, cmd, 1, 0);
1148     if (return_value != IFD_SUCCESS)
1149     return return_value;
1150    
1151     while (1)
1152     {
1153     if (in_len == 0)
1154     {
1155     in_len = 1;
1156 rousseau 2091 return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1157 rousseau 1286 if (return_value != IFD_SUCCESS)
1158     {
1159     DEBUG_CRITICAL("CCID_Receive failed");
1160     return return_value;
1161     }
1162     in_buf = tmp_buf;
1163     }
1164     if (in_len == 0)
1165     {
1166     /* Suppose we should be able to get data.
1167     * If not, error. Set the time-out error */
1168     DEBUG_CRITICAL("error: in_len = 0");
1169     return IFD_RESPONSE_TIMEOUT;
1170     }
1171    
1172     /* Start to process the procedure bytes */
1173     if (*in_buf == 0x60)
1174     {
1175     in_len = 0;
1176     return_value = CCID_Transmit(reader_index, 0, cmd, 1, 0);
1177    
1178     if (return_value != IFD_SUCCESS)
1179     return return_value;
1180    
1181     continue;
1182     }
1183     else if (*in_buf == ins || *in_buf == (ins ^ 0x01))
1184     {
1185     /* ACK => To transfer all remaining data bytes */
1186     in_buf++, in_len--;
1187     if (is_rcv)
1188     return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1189     &rcv_buf, rcv_len, &in_buf, &in_len, exp_len - *rcv_len, 1);
1190     else
1191     return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1192     &rcv_buf, rcv_len, &in_buf, &in_len, snd_len, 0);
1193    
1194     if (*rcv_len == exp_len)
1195     return return_value;
1196    
1197     continue;
1198     }
1199     else if (*in_buf == (ins ^ 0xFF) || *in_buf == (ins ^ 0xFE))
1200     {
1201     /* ACK => To transfer 1 remaining bytes */
1202     in_buf++, in_len--;
1203     return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1204     &rcv_buf, rcv_len, &in_buf, &in_len, 1, is_rcv);
1205    
1206     if (return_value != IFD_SUCCESS)
1207     return return_value;
1208    
1209     continue;
1210     }
1211     else if ((*in_buf & 0xF0) == 0x60 || (*in_buf & 0xF0) == 0x90)
1212     /* SW1 */
1213     return T0ProcSW1(reader_index, rcv_buf, rcv_len, in_buf, in_len);
1214    
1215     /* Error, unrecognized situation found */
1216     DEBUG_CRITICAL2("Unrecognized Procedure byte (0x%02X) found!", *in_buf);
1217     return return_value;
1218     }
1219    
1220     return return_value;
1221     } /* CmdXfrBlockCHAR_T0 */
1222    
1223    
1224     /*****************************************************************************
1225     *
1226 rousseau 614 * CmdXfrBlockTPDU_T1
1227     *
1228     ****************************************************************************/
1229 rousseau 1106 static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
1230     unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1231 rousseau 892 unsigned char rx_buffer[])
1232 rousseau 614 {
1233 rousseau 994 RESPONSECODE return_value = IFD_SUCCESS;
1234 rousseau 1073 int ret;
1235 rousseau 614
1236 rousseau 2092 DEBUG_COMM3("T=1: %d and %d bytes", tx_length, *rx_length);
1237 rousseau 614
1238 rousseau 1106 ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
1239     tx_buffer, tx_length, rx_buffer, *rx_length);
1240 rousseau 614
1241 rousseau 1073 if (ret < 0)
1242 rousseau 614 {
1243 rousseau 659 *rx_length = 0;
1244 rousseau 614 return_value = IFD_COMMUNICATION_ERROR;
1245 rousseau 659 }
1246 rousseau 1073 else
1247     *rx_length = ret;
1248 rousseau 614
1249     return return_value;
1250     } /* CmdXfrBlockTPDU_T1 */
1251    
1252    
1253     /*****************************************************************************
1254     *
1255 rousseau 617 * SetParameters
1256     *
1257     ****************************************************************************/
1258 rousseau 1106 RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
1259     unsigned int length, unsigned char buffer[])
1260 rousseau 617 {
1261     unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
1262 rousseau 1106 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1263 rousseau 617
1264     DEBUG_COMM2("length: %d bytes", length);
1265    
1266     cmd[0] = 0x61; /* SetParameters */
1267     i2dw(length, cmd+1); /* APDU length */
1268 rousseau 1092 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
1269 rousseau 1150 cmd[6] = (*ccid_descriptor->pbSeq)++;
1270 rousseau 617 cmd[7] = protocol; /* bProtocolNum */
1271     cmd[8] = cmd[9] = 0; /* RFU */
1272 rousseau 1301
1273     /* check that the command is not too large */
1274     if (length > CMD_BUF_SIZE)
1275     return IFD_NOT_SUPPORTED;
1276    
1277 rousseau 617 memcpy(cmd+10, buffer, length);
1278    
1279 rousseau 1106 if (WritePort(reader_index, 10+length, cmd) != STATUS_SUCCESS)
1280 rousseau 617 return IFD_COMMUNICATION_ERROR;
1281    
1282     length = sizeof(cmd);
1283 rousseau 1106 if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
1284 rousseau 617 return IFD_COMMUNICATION_ERROR;
1285    
1286     if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1287     {
1288 rousseau 990 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
1289 rousseau 1212 if (0x00 == cmd[ERROR_OFFSET]) /* command not supported */
1290     return IFD_NOT_SUPPORTED;
1291     else
1292     return IFD_COMMUNICATION_ERROR;
1293 rousseau 617 }
1294    
1295     return IFD_SUCCESS;
1296     } /* SetParameters */
1297    
1298    
1299     /*****************************************************************************
1300     *
1301 rousseau 1286 * isCharLevel
1302     *
1303     ****************************************************************************/
1304     int isCharLevel(int reader_index)
1305     {
1306     return CCID_CLASS_CHARACTER == (get_ccid_descriptor(reader_index)->dwFeatures & CCID_CLASS_EXCHANGE_MASK);
1307     } /* isCharLevel */
1308    
1309    
1310     /*****************************************************************************
1311     *
1312 rousseau 407 * i2dw
1313     *
1314     ****************************************************************************/
1315 rousseau 1068 static void i2dw(int value, unsigned char buffer[])
1316 rousseau 269 {
1317     buffer[0] = value & 0xFF;
1318     buffer[1] = (value >> 8) & 0xFF;
1319     buffer[2] = (value >> 16) & 0xFF;
1320     buffer[3] = (value >> 24) & 0xFF;
1321     } /* i2dw */
1322    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5