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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5