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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 614 by rousseau, Thu Jan 15 14:09:10 2004 UTC revision 2472 by rousseau, Thu Mar 8 12:53:18 2007 UTC
# Line 1  Line 1 
1  /*  /*
2      commands.c: Commands sent to the card      commands.c: Commands sent to the card
3      Copyright (C) 2003   Ludovic Rousseau      Copyright (C) 2003-2004   Ludovic Rousseau
4    
5      This program is free software; you can redistribute it and/or modify      This library is free software; you can redistribute it and/or
6      it under the terms of the GNU General Public License as published by      modify it under the terms of the GNU Lesser General Public
7      the Free Software Foundation; either version 2 of the License, or      License as published by the Free Software Foundation; either
8      (at your option) any later version.      version 2.1 of the License, or (at your option) any later version.
9    
10      This program is distributed in the hope that it will be useful,      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      GNU General Public License for more details.      Lesser General Public License for more details.
14    
15      You should have received a copy of the GNU General Public License      You should have received a copy of the GNU Lesser General Public
16      along with this program; if not, write to the Free Software      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      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18  */  */
19    
20  /*  /*
# Line 23  Line 23 
23    
24  #include <string.h>  #include <string.h>
25  #include <stdlib.h>  #include <stdlib.h>
26    #include <errno.h>
27    #include <pcsclite.h>
28    #include <ifdhandler.h>
29    #include <reader.h>
30    
 #include "pcscdefines.h"  
31  #include "commands.h"  #include "commands.h"
32  #include "protocol_t1/protocol_t1.h"  #include "openct/proto-t1.h"
33  #include "ccid.h"  #include "ccid.h"
34  #include "defs.h"  #include "defs.h"
35  #include "ifdhandler.h"  #include "ccid_ifdhandler.h"
36  #include "config.h"  #include "config.h"
37  #include "debug.h"  #include "debug.h"
38    
39    /* All the pinpad readers I used are more or less bogus
40     * I use code to change the user command and make the firmware happy */
41    #define BOGUS_PINPAD_FIRMWARE
42    
43    #define max( a, b )   ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
44    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
45    #define IFD_ERROR_INSUFFICIENT_BUFFER 700
46    
47    /* internal functions */
48    static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
49            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
50            unsigned char rx_buffer[]);
51    
52    static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
53            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
54            unsigned char rx_buffer[]);
55    
56    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index, unsigned int
57            tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned
58            char rx_buffer[]);
59    
60    static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
61            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
62            unsigned char rx_buffer[]);
63    
64    static void i2dw(int value, unsigned char *buffer);
65    
66    
67  /*****************************************************************************  /*****************************************************************************
68   *   *
69   *                                      CmdPowerOn   *                                      CmdPowerOn
70   *   *
71   ****************************************************************************/   ****************************************************************************/
72  RESPONSECODE CmdPowerOn(int lun, int * nlength, unsigned char buffer[])  RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
73            unsigned char buffer[], int voltage)
74  {  {
75          unsigned char cmd[10];          unsigned char cmd[10];
76          status_t res;          status_t res;
77          int atr_len, length, count = 1;          int length, count = 1;
78            unsigned int atr_len;
79          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
80          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
81    
82            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
83            {
84                    int r;
85                    unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
86    
87                    /* first power off to reset the ICC state machine */
88                    r = CmdPowerOff(reader_index);
89                    if (r != IFD_SUCCESS)
90                            return r;
91    
92                    /* wait for ready */
93                    r = CmdGetSlotStatus(reader_index, pcbuffer);
94                    if (r != IFD_SUCCESS)
95                            return r;
96    
97                    /* Power On */
98                    r = ControlUSB(reader_index, 0xA1, 0x62, 0, buffer, *nlength);
99    
100                    /* we got an error? */
101                    if (r < 0)
102                    {
103                            DEBUG_INFO2("ICC Power On failed: %s", strerror(errno));
104                            return IFD_COMMUNICATION_ERROR;
105                    }
106    
107                    *nlength = r;
108    
109                    return IFD_SUCCESS;
110            }
111    
112            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
113            {
114                    int r;
115                    unsigned char tmp[MAX_ATR_SIZE+1];
116    
117                    /* first power off to reset the ICC state machine */
118                    r = CmdPowerOff(reader_index);
119                    if (r != IFD_SUCCESS)
120                            return r;
121    
122                    /* Power On */
123                    r = ControlUSB(reader_index, 0x21, 0x62, 1, NULL, 0);
124    
125                    /* we got an error? */
126                    if (r < 0)
127                    {
128                            DEBUG_INFO2("ICC Power On failed: %s", strerror(errno));
129                            return IFD_COMMUNICATION_ERROR;
130                    }
131    
132                    /* Data Block */
133                    r = ControlUSB(reader_index, 0xA1, 0x6F, 0, tmp, sizeof(tmp));
134    
135                    /* we got an error? */
136                    if (r < 0)
137                    {
138                            DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno));
139                            return IFD_COMMUNICATION_ERROR;
140                    }
141    
142                    if (tmp[0] != 0x00)
143                    {
144                            DEBUG_CRITICAL2("bResponseType: 0x%02X", tmp[0]);
145    
146                            /* Status Information? */
147                            if (0x40 == tmp[0])
148                                    ccid_error(tmp[2], __FILE__, __LINE__, __FUNCTION__);
149                            return IFD_COMMUNICATION_ERROR;
150                    }
151    
152                    DEBUG_INFO_XXD("Data Block: ", tmp, r);
153                    if (*nlength > r-1)
154                            *nlength = r-1;
155                    memcpy(buffer, tmp+1, *nlength);
156    
157                    return IFD_SUCCESS;
158            }
159    
160          /* store length of buffer[] */          /* store length of buffer[] */
161          length = *nlength;          length = *nlength;
162    
163            if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)
164                    voltage = 0;    /* automatic voltage selection */
165    
166  again:  again:
167          cmd[0] = 0x62; /* IccPowerOn */          cmd[0] = 0x62; /* IccPowerOn */
168          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
169          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
170          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
171          if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)          cmd[7] = voltage;
                 cmd[7] = 0x00;  /* Automatic voltage selection */  
         else  
                 cmd[7] = 0x01;  /* 5.0V */  
172          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = cmd[9] = 0; /* RFU */
173    
174          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
175          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
176                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
177    
# Line 68  again: Line 179  again:
179          /* needed if we go back after a switch to ISO mode */          /* needed if we go back after a switch to ISO mode */
180          *nlength = length;          *nlength = length;
181    
182          res = ReadPort(lun, nlength, buffer);          res = ReadPort(reader_index, nlength, buffer);
183          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
184                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
185    
186            if (*nlength < STATUS_OFFSET+1)
187            {
188                    DEBUG_CRITICAL2("Not enough data received: %d bytes", *nlength);
189                    return IFD_COMMUNICATION_ERROR;
190            }
191    
192          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
193          {          {
194                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
195    
196                  /* Protocol error in EMV mode */                  if (0xBB == buffer[ERROR_OFFSET] &&     /* Protocol error in EMV mode */
197                  if (buffer[ERROR_OFFSET] == 0xBB &&                          ((GEMPC433 == ccid_descriptor->readerID)
198                          ccid_descriptor->readerID == GEMPC433)                          || (CHERRYXX33 == ccid_descriptor->readerID)))
199                  {                  {
200                          if ((return_value = CmdEscape(lun, ESC_GEMPC_SET_ISO_MODE)) != IFD_SUCCESS)                          unsigned char cmd_tmp[] = {0x1F, 0x01};
201                            unsigned char res_tmp[1];
202                            unsigned int res_length = sizeof(res_tmp);
203    
204                            if ((return_value = CmdEscape(reader_index, cmd_tmp,
205                                    sizeof(cmd_tmp), res_tmp, &res_length)) != IFD_SUCCESS)
206                                  return return_value;                                  return return_value;
207    
208                          /* avoid looping if we can't switch mode */                          /* avoid looping if we can't switch mode */
# Line 90  again: Line 212  again:
212                                  DEBUG_CRITICAL("Can't set reader in ISO mode");                                  DEBUG_CRITICAL("Can't set reader in ISO mode");
213                  }                  }
214    
215                    /* continue with 3 volts and 5 volts */
216                    if (voltage > 1)
217                    {
218                            const char *voltage_code[] = { "auto", "5V", "3V", "1.8V" };
219    
220                            DEBUG_INFO3("Power up with %s failed. Try with %s.",
221                                    voltage_code[voltage], voltage_code[voltage-1]);
222                            voltage--;
223                            goto again;
224                    }
225    
226                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
227          }          }
228    
# Line 100  again: Line 233  again:
233          else          else
234                  *nlength = atr_len;                  *nlength = atr_len;
235    
236          memcpy(buffer, buffer+10, atr_len);          memmove(buffer, buffer+10, atr_len);
237    
238          return return_value;          return return_value;
239  } /* CmdPowerOn */  } /* CmdPowerOn */
# Line 108  again: Line 241  again:
241    
242  /*****************************************************************************  /*****************************************************************************
243   *   *
244     *                                      SecurePINVerify
245     *
246     ****************************************************************************/
247    RESPONSECODE SecurePINVerify(unsigned int reader_index,
248            unsigned char TxBuffer[], unsigned int TxLength,
249            unsigned char RxBuffer[], unsigned int *RxLength)
250    {
251            unsigned char cmd[11+14+CMD_BUF_SIZE];
252            unsigned int a, b;
253            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
254            int old_read_timeout;
255            RESPONSECODE ret;
256    
257            cmd[0] = 0x69;  /* Secure */
258            cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
259            cmd[6] = (*ccid_descriptor->pbSeq)++;
260            cmd[7] = 0;             /* bBWI */
261            cmd[8] = 0;             /* wLevelParameter */
262            cmd[9] = 0;
263            cmd[10] = 0;    /* bPINOperation: PIN Verification */
264    
265            /* 19 is the size of the PCSCv2 PIN verify structure
266             * The equivalent CCID structure is only 14-bytes long */
267            if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */
268            {
269                    DEBUG_INFO3("Command too long: %d > %d", TxLength, 19+CMD_BUF_SIZE);
270                    return IFD_NOT_SUPPORTED;
271            }
272    
273            if (TxLength < 19+4 /* 4 = APDU size */)        /* command too short? */
274            {
275                    DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4);
276                    return IFD_NOT_SUPPORTED;
277            }
278    
279            if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */
280            {
281                    DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 15) + 19, TxLength);
282                    return IFD_NOT_SUPPORTED;
283            }
284    
285            /* make sure bEntryValidationCondition is valid
286             * The Cherry XX44 reader crashes with a wrong value */
287            if ((0x00 == TxBuffer[7]) || (TxBuffer[7] > 0x07))
288            {
289                    DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
290                            TxBuffer[7]);
291                    TxBuffer[7] = 0x02;
292            }
293    
294    #ifdef BOGUS_PINPAD_FIRMWARE
295            /* bug circumvention for the GemPC Pinpad */
296            if (GEMPCPINPAD == ccid_descriptor->readerID)
297            {
298                    /* the firmware reject the cases: 00h No string and FFh default
299                     * CCID message. The only value supported is 01h (display 1 message) */
300                    if (0x01 != TxBuffer[8])
301                    {
302                            DEBUG_INFO2("Correct bNumberMessage for GemPC Pinpad (was %d)",
303                                    TxBuffer[8]);
304                            TxBuffer[8] = 0x01;
305                    }
306    
307                    /* The reader does not support, and actively reject, "max size reached"
308                     * and "timeout occured" validation conditions */
309                    if (0x02 != TxBuffer[7])
310                    {
311                            DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
312                                    TxBuffer[7]);
313                            TxBuffer[7] = 0x02;     /* validation key pressed */
314                    }
315    
316            }
317    #endif
318    
319            /* T=1 Protocol Management for a TPDU reader */
320            if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
321                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
322            {
323                    ct_buf_t sbuf;
324                    unsigned char sdata[T1_BUFFER_SIZE];
325    
326                    /* Initialize send buffer with the APDU */
327                    ct_buf_set(&sbuf,
328                            (void *)(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, abData)),
329                            TxLength - offsetof(PIN_VERIFY_STRUCTURE, abData));
330    
331                    /* Create T=1 block */
332                    ret = t1_build(&((get_ccid_slot(reader_index))->t1),
333                            sdata, 0, T1_I_BLOCK, &sbuf, NULL);
334    
335                    /* Increment the sequence numbers  */
336                    get_ccid_slot(reader_index)->t1.ns ^= 1;
337                    get_ccid_slot(reader_index)->t1.nr ^= 1;
338    
339                    /* Copy the generated T=1 block prologue into the teoprologue
340                     * of the CCID command */
341                    memcpy(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, bTeoPrologue),
342                            sdata, 3);
343            }
344    
345            /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
346            for (a = 11, b = 0; b < TxLength; b++)
347            {
348                    if (1 == b) /* bTimeOut2 field */
349                            /* Ignore the second timeout as there's nothing we can do with
350                             * it currently */
351                            continue;
352    
353                    if ((b >= 15) && (b <= 18)) /* ulDataLength field (4 bytes) */
354                            /* the ulDataLength field is not present in the CCID frame
355                             * so do not copy */
356                            continue;
357    
358                    /* copy the CCID block 'verbatim' */
359                    cmd[a] = TxBuffer[b];
360                    a++;
361            }
362    
363            /* SPR532 and Case 1 APDU */
364            if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
365            {
366                    RESPONSECODE return_value;
367                    unsigned char cmd_tmp[] = { 0x80, 0x02, 0x00 };
368                    unsigned char res_tmp[1];
369                    unsigned int res_length = sizeof(res_tmp);
370    
371                    /* the SPR532 will append the PIN code without any padding */
372                    return_value = CmdEscape(reader_index, cmd_tmp, sizeof(cmd_tmp),
373                            res_tmp, &res_length);
374                    if (return_value != IFD_SUCCESS)
375                    {
376                            ccid_error(res_tmp[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);
377                            return return_value;
378                    }
379            }
380    
381            i2dw(a - 10, cmd + 1);  /* CCID message length */
382    
383            old_read_timeout = ccid_descriptor -> readTimeout;
384            ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10);       /* at least 30 seconds */
385    
386            if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
387                    return IFD_COMMUNICATION_ERROR;
388    
389            ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
390    
391            /* T=1 Protocol Management for a TPDU reader */
392            if ((IFD_SUCCESS == ret)
393                    && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
394                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
395            {
396                    /* timeout and cancel cases are faked by CCID_Receive() */
397                    if (2 == *RxLength)
398                    {
399                            /* Decrement the sequence numbers since no TPDU was sent */
400                            get_ccid_slot(reader_index)->t1.ns ^= 1;
401                            get_ccid_slot(reader_index)->t1.nr ^= 1;
402                    }
403                    else
404                    {
405                            /* get only the T=1 data */
406                            /* FIXME: manage T=1 error blocks */
407                            memmove(RxBuffer, RxBuffer+3, *RxLength -4);
408                            *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
409                    }
410            }
411    
412            ccid_descriptor -> readTimeout = old_read_timeout;
413            return ret;
414    } /* SecurePINVerify */
415    
416    
417    /*****************************************************************************
418     *
419     *                                      SecurePINModify
420     *
421     ****************************************************************************/
422    RESPONSECODE SecurePINModify(unsigned int reader_index,
423            unsigned char TxBuffer[], unsigned int TxLength,
424            unsigned char RxBuffer[], unsigned int *RxLength)
425    {
426            unsigned char cmd[11+19+CMD_BUF_SIZE];
427            unsigned int a, b;
428            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
429            int old_read_timeout;
430            RESPONSECODE ret;
431    #ifdef BOGUS_PINPAD_FIRMWARE
432            int bNumberMessages = 0; /* for GemPC Pinpad */
433    #endif
434    
435            cmd[0] = 0x69;  /* Secure */
436            cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
437            cmd[6] = (*ccid_descriptor->pbSeq)++;
438            cmd[7] = 0;             /* bBWI */
439            cmd[8] = 0;             /* wLevelParameter */
440            cmd[9] = 0;
441            cmd[10] = 1;    /* bPINOperation: PIN Modification */
442    
443            /* 24 is the size of the PCSC PIN modify structure
444             * The equivalent CCID structure is only 18 or 19-bytes long */
445            if (TxLength > 24+CMD_BUF_SIZE) /* command too large? */
446            {
447                    DEBUG_INFO3("Command too long: %d > %d", TxLength, 24+CMD_BUF_SIZE);
448                    return IFD_NOT_SUPPORTED;
449            }
450    
451            if (TxLength < 24+4 /* 4 = APDU size */) /* command too short? */
452            {
453                    DEBUG_INFO3("Command too short: %d < %d", TxLength, 24+4);
454                    return IFD_NOT_SUPPORTED;
455            }
456    
457            if (dw2i(TxBuffer, 20) + 24 != TxLength) /* ulDataLength field coherency */
458            {
459                    DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 20) + 24, TxLength);
460                    return IFD_NOT_SUPPORTED;
461            }
462    
463            /* Make sure in the beginning if bNumberMessage is valid or not */
464            if (TxBuffer[11] > 3)
465            {
466                    DEBUG_INFO2("Wrong bNumberMessage: %d", TxBuffer[11]);
467                    return IFD_NOT_SUPPORTED;
468            }
469    
470            /* Make sure bEntryValidationCondition is valid
471             * The Cherry XX44 reader crashes with a wrong value */
472            if ((0x00 == TxBuffer[10]) || (TxBuffer[10] > 0x07))
473            {
474                    DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
475                            TxBuffer[10]);
476                    TxBuffer[10] = 0x02;
477            }
478    
479    #ifdef BOGUS_PINPAD_FIRMWARE
480            /* some firmwares are buggy so we try to "correct" the frame */
481            /*
482             * SPR 532 and Cherry ST 2000C has no display but requires _all_
483             * bMsgIndex fields with bNumberMessage set to 0.
484             */
485            if ((SPR532 == ccid_descriptor->readerID)
486                    || (CHERRYST2000 == ccid_descriptor->readerID))
487            {
488                    TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
489                                                                    all bMsgIndex123 are filled */
490                    TxBuffer[14] = TxBuffer[15] = TxBuffer[16] = 0; /* bMsgIndex123 */
491            }
492    
493            /* the bug is a bit different than for the Cherry ST 2000C
494             * with bNumberMessages < 3 the command seems to be accepted
495             * and the card sends 6B 80 */
496            if (CHERRYXX44 == ccid_descriptor->readerID)
497            {
498                    TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
499                                                                    all bMsgIndex123 are filled */
500            }
501    
502            /* bug circumvention for the GemPC Pinpad */
503            if (GEMPCPINPAD == ccid_descriptor->readerID)
504            {
505                    /* The reader does not support, and actively reject, "max size reached"
506                     * and "timeout occured" validation conditions */
507                    if (0x02 != TxBuffer[10])
508                    {
509                            DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
510                                    TxBuffer[10]);
511                            TxBuffer[10] = 0x02;    /* validation key pressed */
512                    }
513    
514                    /* the reader does not support any other value than 3 for the number
515                     * of messages */
516                    bNumberMessages = TxBuffer[11];
517                    if (0x03 != TxBuffer[11])
518                    {
519                            DEBUG_INFO2("Correct bNumberMessages for GemPC Pinpad (was %d)",
520                                    TxBuffer[11]);
521                            TxBuffer[11] = 0x03; /* 3 messages */
522                    }
523            }
524    #endif
525    
526            /* T=1 Protocol Management for a TPDU reader */
527            if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
528                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
529            {
530                    ct_buf_t sbuf;
531                    unsigned char sdata[T1_BUFFER_SIZE];
532    
533                    /* Initialize send buffer with the APDU */
534                    ct_buf_set(&sbuf,
535                            (void *)(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, abData)),
536                            TxLength - offsetof(PIN_MODIFY_STRUCTURE, abData));
537    
538                    /* Create T=1 block */
539                    ret = t1_build(&((get_ccid_slot(reader_index))->t1),
540                            sdata, 0, T1_I_BLOCK, &sbuf, NULL);
541    
542                    /* Increment the sequence numbers  */
543                    get_ccid_slot(reader_index)->t1.ns ^= 1;
544                    get_ccid_slot(reader_index)->t1.nr ^= 1;
545    
546                    /* Copy the generated T=1 block prologue into the teoprologue
547                     * of the CCID command */
548                    memcpy(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, bTeoPrologue),
549                            sdata, 3);
550            }
551    
552            /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
553    
554            /* Do adjustments as needed - CCID spec is not exact with some
555             * details in the format of the structure, per-reader adaptions
556             * might be needed.
557             */
558            for (a = 11, b = 0; b < TxLength; b++)
559            {
560                    if (1 == b) /* bTimeOut2 */
561                            /* Ignore the second timeout as there's nothing we can do with it
562                             * currently */
563                            continue;
564    
565                    if (15 == b) /* bMsgIndex2 */
566                    {
567                            /* in CCID the bMsgIndex2 is present only if bNumberMessage != 0 */
568                            if (0 == TxBuffer[11])
569                                    continue;
570                    }
571    
572                    if (16 == b) /* bMsgIndex3 */
573                    {
574                            /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
575                            if (TxBuffer[11] < 3)
576                                    continue;
577                    }
578    
579                    if ((b >= 20) && (b <= 23)) /* ulDataLength field (4 bytes) */
580                            /* the ulDataLength field is not present in the CCID frame
581                             * so do not copy */
582                            continue;
583    
584                    /* copy to the CCID block 'verbatim' */
585                    cmd[a] = TxBuffer[b];
586                    a++;
587            }
588    
589    #ifdef BOGUS_PINPAD_FIRMWARE
590            if ((SPR532 == ccid_descriptor->readerID)
591                    || (CHERRYST2000 == ccid_descriptor->readerID))
592            {
593                    cmd[21] = 0x00; /* set bNumberMessages to 0 */
594            }
595    
596            if (GEMPCPINPAD == ccid_descriptor->readerID)
597                    cmd[21] = bNumberMessages;      /* restore the real value */
598    #endif
599    
600            /* We know the size of the CCID message now */
601            i2dw(a - 10, cmd + 1);  /* command length (includes bPINOperation) */
602    
603            old_read_timeout = ccid_descriptor -> readTimeout;
604            ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10);       /* at least 30 seconds */
605    
606            if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
607                    return IFD_COMMUNICATION_ERROR;
608    
609            ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
610    
611            /* T=1 Protocol Management for a TPDU reader */
612            if ((IFD_SUCCESS == ret)
613                    && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
614                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
615            {
616                    /* timeout and cancel cases are faked by CCID_Receive() */
617                    if (2 == *RxLength)
618                    {
619                            /* Decrement the sequence numbers since no TPDU was sent */
620                            get_ccid_slot(reader_index)->t1.ns ^= 1;
621                            get_ccid_slot(reader_index)->t1.nr ^= 1;
622                    }
623                    else
624                    {
625                            /* get only the T=1 data */
626                            /* FIXME: manage T=1 error blocks */
627                            memmove(RxBuffer, RxBuffer+3, *RxLength -4);
628                            *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
629                    }
630            }
631    
632            ccid_descriptor -> readTimeout = old_read_timeout;
633            return ret;
634    } /* SecurePINModify */
635    
636    
637    /*****************************************************************************
638     *
639   *                                      Escape   *                                      Escape
640   *   *
641   ****************************************************************************/   ****************************************************************************/
642  RESPONSECODE CmdEscape(int lun, int command)  RESPONSECODE CmdEscape(unsigned int reader_index,
643            const unsigned char TxBuffer[], unsigned int TxLength,
644            unsigned char RxBuffer[], unsigned int *RxLength)
645  {  {
646          unsigned char cmd[12];          unsigned char *cmd_in, *cmd_out;
647          status_t res;          status_t res;
648          int length;          unsigned int length_in, length_out;
649          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
650          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
651    
652          cmd[0] = 0x6B; /* PC_to_RDR_Escape */  again:
653          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          /* allocate buffers */
654          cmd[5] = 0;     /* slot number */          length_in = 10 + TxLength;
655          cmd[6] = ccid_descriptor->bSeq++;          if (NULL == (cmd_in = malloc(length_in)))
656          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */                  return IFD_COMMUNICATION_ERROR;
657    
658          switch (command)          length_out = 10 + *RxLength;
659            if (NULL == (cmd_out = malloc(length_out)))
660          {          {
661                  /* Gemplus proprietary */                  free(cmd_in);
662                  case ESC_GEMPC_SET_ISO_MODE:                  return IFD_COMMUNICATION_ERROR;
663                          DEBUG_INFO("Switch reader in ISO mode");          }
                         cmd[10] = 0x1F; /* switch mode */  
                         cmd[11] = 0x01; /* set ISO mode */  
                         cmd[1] = 2;     /* length of data */  
                         length = 12;  
                         break;  
664    
665                  /* Gemplus proprietary */          cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
666                  case ESC_GEMPC_SET_APDU_MODE:          i2dw(length_in - 10, cmd_in+1); /* dwLength */
667                          DEBUG_INFO("Switch reader in APDU mode");          cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
668                          cmd[10] = 0xA0; /* switch mode */          cmd_in[6] = (*ccid_descriptor->pbSeq)++;
669                          cmd[11] = 0x02; /* set APDU mode */          cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
                         cmd[1] = 2;     /* length of data */  
                         length = 12;  
                         break;  
670    
671                  default:          /* copy the command */
672                          DEBUG_CRITICAL2("Unkown Escape command: %d", command);          memcpy(&cmd_in[10], TxBuffer, TxLength);
                         return return_value;  
         }  
673    
674          res = WritePort(lun, length, cmd);          res = WritePort(reader_index, length_in, cmd_in);
675            free(cmd_in);
676          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
677            {
678                    free(cmd_out);
679                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
680            }
681    
682            res = ReadPort(reader_index, &length_out, cmd_out);
683    
684            /* replay the command if NAK
685             * This (generally) happens only for the first command sent to the reader
686             * with the serial protocol so it is not really needed for all the other
687             * ReadPort() calls */
688            if (STATUS_COMM_NAK == res)
689            {
690                    free(cmd_out);
691                    goto again;
692            }
693    
         length = sizeof(cmd);  
         res = ReadPort(lun, &length, cmd);  
694          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
695            {
696                    free(cmd_out);
697                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
698            }
699    
700          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (length_out < STATUS_OFFSET+1)
701            {
702                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length_out);
703                    return IFD_COMMUNICATION_ERROR;
704            }
705    
706            if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)
707          {          {
708                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
709                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
710          }          }
711    
712            /* copy the response */
713            length_out = dw2i(cmd_out, 1);
714            if (length_out > *RxLength)
715                    length_out = *RxLength;
716            *RxLength = length_out;
717            memcpy(RxBuffer, &cmd_out[10], length_out);
718    
719            free(cmd_out);
720    
721          return return_value;          return return_value;
722  } /* Escape */  } /* Escape */
723    
# Line 174  RESPONSECODE CmdEscape(int lun, int comm Line 727  RESPONSECODE CmdEscape(int lun, int comm
727   *                                      CmdPowerOff   *                                      CmdPowerOff
728   *   *
729   ****************************************************************************/   ****************************************************************************/
730  RESPONSECODE CmdPowerOff(int lun)  RESPONSECODE CmdPowerOff(unsigned int reader_index)
731  {  {
732          unsigned char cmd[10];          unsigned char cmd[10];
733          status_t res;          status_t res;
734          int length;          unsigned int length;
735          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
736          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
737    
738            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
739            {
740                    int r;
741    
742                    /* PowerOff */
743                    r = ControlUSB(reader_index, 0x21, 0x63, 0, NULL, 0);
744    
745                    /* we got an error? */
746                    if (r < 0)
747                    {
748                            DEBUG_INFO2("ICC Power Off failed: %s", strerror(errno));
749                            return IFD_COMMUNICATION_ERROR;
750                    }
751    
752                    return IFD_SUCCESS;
753            }
754    
755            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
756            {
757                    int r;
758                    unsigned char buffer[3];
759    
760                    /* PowerOff */
761                    r = ControlUSB(reader_index, 0x21, 0x63, 0, NULL, 0);
762    
763                    /* we got an error? */
764                    if (r < 0)
765                    {
766                            DEBUG_INFO2("ICC Power Off failed: %s", strerror(errno));
767                            return IFD_COMMUNICATION_ERROR;
768                    }
769    
770                    /* SlotStatus */
771                    r = ControlUSB(reader_index, 0xA1, 0x81, 0, buffer, sizeof(buffer));
772    
773                    /* we got an error? */
774                    if (r < 0)
775                    {
776                            DEBUG_INFO2("ICC SlotStatus failed: %s", strerror(errno));
777                            return IFD_COMMUNICATION_ERROR;
778                    }
779    
780                    return IFD_SUCCESS;
781            }
782    
783          cmd[0] = 0x63; /* IccPowerOff */          cmd[0] = 0x63; /* IccPowerOff */
784          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
785          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
786          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
787          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
788    
789          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
790          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
791                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
792    
793          length = sizeof(cmd);          length = sizeof(cmd);
794          res = ReadPort(lun, &length, cmd);          res = ReadPort(reader_index, &length, cmd);
795          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
796                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
797    
798            if (length < STATUS_OFFSET+1)
799            {
800                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
801                    return IFD_COMMUNICATION_ERROR;
802            }
803    
804          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
805          {          {
806                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
807                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
808          }          }
809    
# Line 212  RESPONSECODE CmdPowerOff(int lun) Line 816  RESPONSECODE CmdPowerOff(int lun)
816   *                                      CmdGetSlotStatus   *                                      CmdGetSlotStatus
817   *   *
818   ****************************************************************************/   ****************************************************************************/
819  RESPONSECODE CmdGetSlotStatus(int lun, unsigned char buffer[])  RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
820  {  {
821          unsigned char cmd[10];          unsigned char cmd[10];
822          status_t res;          status_t res;
823          int length;          unsigned int length;
824          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
825          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
826    
827            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
828            {
829                    int r;
830                    unsigned char status[1];
831    
832    again_status:
833                    /* SlotStatus */
834                    r = ControlUSB(reader_index, 0xA1, 0xA0, 0, status, sizeof(status));
835    
836                    /* we got an error? */
837                    if (r < 0)
838                    {
839                            DEBUG_INFO2("ICC Slot Status failed: %s", strerror(errno));
840                            if (ENODEV == errno)
841                                    return IFD_NO_SUCH_DEVICE;
842                            return IFD_COMMUNICATION_ERROR;
843                    }
844    
845                    /* busy */
846                    if (status[0] & 0x40)
847                    {
848                            DEBUG_INFO2("Busy: 0x%02X", status[0]);
849                            usleep(1000 * 10);
850                            goto again_status;
851                    }
852    
853                    /* simulate a CCID bStatus */
854                    /* present and active by default */
855                    buffer[7] = CCID_ICC_PRESENT_ACTIVE;
856    
857                    /* mute */
858                    if (0x80 == status[0])
859                            buffer[7] = CCID_ICC_ABSENT;
860    
861                    /* store the status for CmdXfrBlockCHAR_T0() */
862                    buffer[0] = status[0];
863    
864                    return IFD_SUCCESS;
865            }
866    
867            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
868            {
869                    int r;
870                    unsigned char buffer_tmp[3];
871    
872                    /* SlotStatus */
873                    r = ControlUSB(reader_index, 0xA1, 0x81, 0, buffer_tmp,
874                            sizeof(buffer_tmp));
875    
876                    /* we got an error? */
877                    if (r < 0)
878                    {
879                            DEBUG_INFO2("ICC Slot Status failed: %s", strerror(errno));
880                            if (ENODEV == errno)
881                                    return IFD_NO_SUCH_DEVICE;
882                            return IFD_COMMUNICATION_ERROR;
883                    }
884    
885                    /* simulate a CCID bStatus */
886                    switch (buffer_tmp[1] & 0x03)
887                    {
888                            case 0:
889                                    buffer[7] = CCID_ICC_PRESENT_ACTIVE;
890                                    break;
891                            case 1:
892                                    buffer[7] = CCID_ICC_PRESENT_INACTIVE;
893                                    break;
894                            case 2:
895                            case 3:
896                                    buffer[7] = CCID_ICC_ABSENT;
897                    }
898                    return IFD_SUCCESS;
899            }
900    
901          cmd[0] = 0x65; /* GetSlotStatus */          cmd[0] = 0x65; /* GetSlotStatus */
902          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
903          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
904          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
905          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
906    
907          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
908          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
909            {
910                    if (STATUS_NO_SUCH_DEVICE == res)
911                            return IFD_NO_SUCH_DEVICE;
912                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
913            }
914    
915          length = SIZE_GET_SLOT_STATUS;          length = SIZE_GET_SLOT_STATUS;
916          res = ReadPort(lun, &length, buffer);          res = ReadPort(reader_index, &length, buffer);
917          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
918                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
919    
920            if (length < STATUS_OFFSET+1)
921            {
922                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
923                    return IFD_COMMUNICATION_ERROR;
924            }
925    
926          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
927          {          {
928                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */  #ifdef O2MICRO_OZ776_PATCH
929                  return_value = IFD_COMMUNICATION_ERROR;                  /* the O2MICRO OZ 776 reader sends card absent or mute errors
930                     * when no card is inserted */
931                    if (! ((OZ776 == ccid_descriptor->readerID)
932                            && (buffer[ERROR_OFFSET] == 0xFE)))
933    #endif
934                    ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
935    
936                    /* card absent or mute is not an communication error */
937                    if (buffer[ERROR_OFFSET] != 0xFE)
938                            return_value = IFD_COMMUNICATION_ERROR;
939          }          }
940    
941          return return_value;          return return_value;
# Line 250  RESPONSECODE CmdGetSlotStatus(int lun, u Line 947  RESPONSECODE CmdGetSlotStatus(int lun, u
947   *                                      CmdXfrBlock   *                                      CmdXfrBlock
948   *   *
949   ****************************************************************************/   ****************************************************************************/
950  RESPONSECODE CmdXfrBlock(int lun, int tx_length, unsigned char tx_buffer[],  RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
951          int *rx_length, unsigned char rx_buffer[], int protocol)          unsigned char tx_buffer[], unsigned int *rx_length,
952            unsigned char rx_buffer[], int protocol)
953  {  {
954          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
955          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
   
         /* command length too big for CCID reader? */  
         if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength)  
         {  
                 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",  
                         tx_length, ccid_descriptor->dwMaxCCIDMessageLength);  
                 return_value = IFD_COMMUNICATION_ERROR;  
                 goto clean_up_and_return;  
         }  
956    
957          /* command length too big for CCID driver? */          /* APDU or TPDU? */
958          if (tx_length > CMD_BUF_SIZE)          switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)
         {  
                 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",  
                         tx_length, CMD_BUF_SIZE);  
                 return_value = IFD_COMMUNICATION_ERROR;  
                 goto clean_up_and_return;  
         }  
   
         /* APDU or TPDU? */  
         switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)  
959          {          {
960                  case CCID_CLASS_TPDU:                  case CCID_CLASS_TPDU:
961                          if (protocol == T_0)                          if (protocol == T_0)
962                                  return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                                  return_value = CmdXfrBlockTPDU_T0(reader_index,
963                                          rx_length, rx_buffer);                                          tx_length, tx_buffer, rx_length, rx_buffer);
964                          else                          else
965                                  if (protocol == T_1)                                  if (protocol == T_1)
966                                          return_value = CmdXfrBlockTPDU_T1(lun, tx_length,                                          return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
967                                                  tx_buffer, rx_length, rx_buffer);                                                  tx_buffer, rx_length, rx_buffer);
968                                  else                                  else
969                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;
970                          break;                          break;
971    
972                  case CCID_CLASS_SHORT_APDU:                  case CCID_CLASS_SHORT_APDU:
973                            return_value = CmdXfrBlockTPDU_T0(reader_index,
974                                    tx_length, tx_buffer, rx_length, rx_buffer);
975                            break;
976    
977                  case CCID_CLASS_EXTENDED_APDU:                  case CCID_CLASS_EXTENDED_APDU:
978                          /* We only support extended APDU if the reader can support the                          return_value = CmdXfrBlockAPDU_extended(reader_index,
979                           * command length. See test above */                                  tx_length, tx_buffer, rx_length, rx_buffer);
980                          return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                          break;
981                                  rx_length, rx_buffer);  
982                    case CCID_CLASS_CHARACTER:
983                            if (protocol == T_0)
984                                    return_value = CmdXfrBlockCHAR_T0(reader_index, tx_length,
985                                            tx_buffer, rx_length, rx_buffer);
986                            else
987                                    if (protocol == T_1)
988                                            return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
989                                                    tx_buffer, rx_length, rx_buffer);
990                                    else
991                                            return_value = IFD_PROTOCOL_NOT_SUPPORTED;
992                          break;                          break;
993    
994                  default:                  default:
                         *rx_length = 0;  
995                          return_value = IFD_COMMUNICATION_ERROR;                          return_value = IFD_COMMUNICATION_ERROR;
996          }          }
997    
 clean_up_and_return:  
998          return return_value;          return return_value;
999  } /* CmdXfrBlock */  } /* CmdXfrBlock */
1000    
# Line 312  clean_up_and_return: Line 1004  clean_up_and_return:
1004   *                                      CCID_Transmit   *                                      CCID_Transmit
1005   *   *
1006   ****************************************************************************/   ****************************************************************************/
1007  RESPONSECODE CCID_Transmit(int lun, int tx_length, unsigned char tx_buffer[])  RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
1008            const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
1009  {  {
1010          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
1011          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1012            status_t ret;
1013    
1014            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
1015            {
1016                    int r;
1017    
1018                    /* Xfr Block */
1019                    r = ControlUSB(reader_index, 0x21, 0x65, 0, tx_buffer, tx_length);
1020    
1021                    /* we got an error? */
1022                    if (r < 0)
1023                    {
1024                            DEBUG_INFO2("ICC Xfr Block failed: %s", strerror(errno));
1025                            return IFD_COMMUNICATION_ERROR;
1026                    }
1027    
1028                    return IFD_SUCCESS;
1029            }
1030    
1031            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
1032            {
1033                    int r;
1034    
1035                    /* nul block so we are chaining */
1036                    if (NULL == tx_buffer)
1037                            rx_length = 0x10;       /* bLevelParameter */
1038    
1039                    /* Xfr Block */
1040                    DEBUG_COMM2("chain parameter: %d", rx_length);
1041                    r = ControlUSB(reader_index, 0x21, 0x65, rx_length << 8, tx_buffer,
1042                            tx_length);
1043    
1044                    /* we got an error? */
1045                    if (r < 0)
1046                    {
1047                            DEBUG_INFO2("ICC Xfr Block failed: %s", strerror(errno));
1048                            return IFD_COMMUNICATION_ERROR;
1049                    }
1050    
1051                    return IFD_SUCCESS;
1052            }
1053    
1054          cmd[0] = 0x6F; /* XfrBlock */          cmd[0] = 0x6F; /* XfrBlock */
1055          i2dw(tx_length, cmd+1); /* APDU length */          i2dw(tx_length, cmd+1); /* APDU length */
1056          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
1057          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
1058          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = bBWI;  /* extend block waiting timeout */
1059            cmd[8] = rx_length & 0xFF;      /* Expected length, in character mode only */
1060            cmd[9] = (rx_length >> 8) & 0xFF;
1061    
1062            /* check that the command is not too large */
1063            if (tx_length > CMD_BUF_SIZE)
1064            {
1065                    DEBUG_CRITICAL2("TX Length too big: %d", tx_length);
1066                    return IFD_NOT_SUPPORTED;
1067            }
1068    
1069          memcpy(cmd+10, tx_buffer, tx_length);          memcpy(cmd+10, tx_buffer, tx_length);
1070    
1071          if (WritePort(lun, 10+tx_length, cmd) != STATUS_SUCCESS)          ret = WritePort(reader_index, 10+tx_length, cmd);
1072            if (STATUS_NO_SUCH_DEVICE == ret)
1073                    return IFD_NO_SUCH_DEVICE;
1074            if (ret != STATUS_SUCCESS)
1075                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1076    
1077          return IFD_SUCCESS;          return IFD_SUCCESS;
# Line 336  RESPONSECODE CCID_Transmit(int lun, int Line 1083  RESPONSECODE CCID_Transmit(int lun, int
1083   *                                      CCID_Receive   *                                      CCID_Receive
1084   *   *
1085   ****************************************************************************/   ****************************************************************************/
1086  RESPONSECODE CCID_Receive(int lun, int *rx_length, unsigned char rx_buffer[])  RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
1087            unsigned char rx_buffer[], unsigned char *chain_parameter)
1088  {  {
1089          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
1090          int length;          unsigned int length;
1091          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
1092            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1093            status_t ret;
1094    
1095            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
1096            {
1097                    int r;
1098    
1099                    /* Data Block */
1100                    r = ControlUSB(reader_index, 0xA1, 0x6F, 0, rx_buffer, *rx_length);
1101    
1102                    /* we got an error? */
1103                    if (r < 0)
1104                    {
1105                            DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno));
1106                            return IFD_COMMUNICATION_ERROR;
1107                    }
1108    
1109                    return IFD_SUCCESS;
1110            }
1111    
1112            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
1113            {
1114                    int r;
1115                    unsigned char rx_tmp[4];
1116    
1117                    /* read a nul block. buffer need to be at least 4-bytes */
1118                    if (NULL == rx_buffer)
1119                    {
1120                            rx_buffer = rx_tmp;
1121                            *rx_length = sizeof(rx_tmp);
1122                    }
1123    
1124    time_request_ICCD_B:
1125                    /* Data Block */
1126                    r = ControlUSB(reader_index, 0xA1, 0x6F, 0, rx_buffer, *rx_length);
1127    
1128                    /* we got an error? */
1129                    if (r < 0)
1130                    {
1131                            DEBUG_INFO2("ICC Data Block failed: %s", strerror(errno));
1132                            return IFD_COMMUNICATION_ERROR;
1133                    }
1134    
1135                    /* bResponseType */
1136                    switch (rx_buffer[0])
1137                    {
1138                            case 0x00:
1139                                    /* the abData field contains the information created by the
1140                                     * preceding request */
1141                                    break;
1142    
1143                            case 0x40:
1144                                    /* Status Information */
1145                                    ccid_error(rx_buffer[2], __FILE__, __LINE__, __FUNCTION__);
1146                                    return IFD_COMMUNICATION_ERROR;
1147    
1148                            case 0x80:
1149                                    /* Polling */
1150                            {
1151                                    int delay;
1152    
1153                                    delay = (rx_buffer[2] << 8) + rx_buffer[1];
1154                                    DEBUG_COMM2("Pooling delay: %d", delay);
1155    
1156                                    if (0 == delay)
1157                                            /* host select the delay */
1158                                            delay = 1;
1159                                    usleep(delay * 1000 * 10);
1160                                    goto time_request_ICCD_B;
1161                            }
1162    
1163                            case 0x01:
1164                            case 0x02:
1165                            case 0x03:
1166                            case 0x10:
1167                                    /* Extended case
1168                                     * Only valid for Data Block frames */
1169                                    if (chain_parameter)
1170                                            *chain_parameter = rx_buffer[0];
1171                                    break;
1172    
1173                            default:
1174                                    DEBUG_CRITICAL2("Unknown bResponseType: 0x%02X", rx_buffer[0]);
1175                                    return IFD_COMMUNICATION_ERROR;
1176                    }
1177    
1178                    memmove(rx_buffer, rx_buffer+1, r-1);
1179                    *rx_length = r-1;
1180    
1181                    return IFD_SUCCESS;
1182            }
1183    
1184  time_request:  time_request:
1185          length = sizeof(cmd);          length = sizeof(cmd);
1186          if (ReadPort(lun, &length, cmd) != STATUS_SUCCESS)          ret = ReadPort(reader_index, &length, cmd);
1187            if (ret != STATUS_SUCCESS)
1188            {
1189                    if (STATUS_NO_SUCH_DEVICE == ret)
1190                            return IFD_NO_SUCH_DEVICE;
1191                    return IFD_COMMUNICATION_ERROR;
1192            }
1193    
1194            if (length < STATUS_OFFSET+1)
1195            {
1196                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
1197                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1198            }
1199    
1200          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1201          {          {
1202                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
1203                  *rx_length = 0; /* nothing received */                  switch (cmd[ERROR_OFFSET])
1204                  return_value = IFD_COMMUNICATION_ERROR;                  {
1205                            case 0xEF:      /* cancel */
1206                                    if (*rx_length < 2)
1207                                            return IFD_COMMUNICATION_ERROR;
1208                                    rx_buffer[0]= 0x64;
1209                                    rx_buffer[1]= 0x01;
1210                                    *rx_length = 2;
1211                                    return IFD_SUCCESS;
1212    
1213                            case 0xF0:      /* timeout */
1214                                    if (*rx_length < 2)
1215                                            return IFD_COMMUNICATION_ERROR;
1216                                    rx_buffer[0]= 0x64;
1217                                    rx_buffer[1]= 0x00;
1218                                    *rx_length = 2;
1219                                    return IFD_SUCCESS;
1220    
1221                            case 0xFD:      /* Parity error during exchange */
1222                                    return IFD_PARITY_ERROR;
1223    
1224                            default:
1225                                    return IFD_COMMUNICATION_ERROR;
1226                    }
1227          }          }
1228    
1229          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
1230          {          {
1231                  DEBUG_CRITICAL2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);                  DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);
1232                  goto time_request;                  goto time_request;
1233          }          }
1234    
1235          length = dw2i(cmd, 1);          length = dw2i(cmd, 1);
1236          if (length < *rx_length)          if (length <= *rx_length)
1237                  *rx_length = length;                  *rx_length = length;
1238          else          else
1239            {
1240                    DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);
1241                  length = *rx_length;                  length = *rx_length;
1242                    return_value = IFD_ERROR_INSUFFICIENT_BUFFER;
1243            }
1244          memcpy(rx_buffer, cmd+10, length);          memcpy(rx_buffer, cmd+10, length);
1245    
1246            /* Extended case?
1247             * Only valid for RDR_to_PC_DataBlock frames */
1248            if (chain_parameter)
1249                    *chain_parameter = cmd[CHAIN_PARAMETER_OFFSET];
1250    
1251          return return_value;          return return_value;
1252  } /* CCID_Receive */  } /* CCID_Receive */
1253    
1254    
1255  /*****************************************************************************  /*****************************************************************************
1256   *   *
1257     *                                      CmdXfrBlockAPDU_extended
1258     *
1259     ****************************************************************************/
1260    static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
1261            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1262            unsigned char rx_buffer[])
1263    {
1264            RESPONSECODE return_value;
1265            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1266            unsigned char chain_parameter;
1267            unsigned int local_tx_length, sent_length;
1268            unsigned int local_rx_length, received_length;
1269            int buffer_overflow = 0;
1270    
1271            if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
1272            {
1273                    /* length is on 16-bits only
1274                     * if a size > 0x1000 is used then usb_control_msg() fails with
1275                     * "Invalid argument" */
1276                    if (*rx_length > 0x1000)
1277                            *rx_length = 0x1000;
1278            }
1279    
1280            DEBUG_COMM2("T=0 (extended): %d bytes", tx_length);
1281    
1282            /* send the APDU */
1283            sent_length = 0;
1284    
1285            /* we suppose one command is enough */
1286            chain_parameter = 0x00;
1287    
1288            local_tx_length = tx_length - sent_length;
1289            if (local_tx_length > CMD_BUF_SIZE)
1290            {
1291                    local_tx_length = CMD_BUF_SIZE;
1292                    /* the command APDU begins with this command, and continue in the next
1293                     * PC_to_RDR_XfrBlock */
1294                    chain_parameter = 0x01;
1295            }
1296            if (local_tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
1297            {
1298                    local_tx_length = ccid_descriptor->dwMaxCCIDMessageLength-10;
1299                    chain_parameter = 0x01;
1300            }
1301    
1302    send_next_block:
1303            return_value = CCID_Transmit(reader_index, local_tx_length, tx_buffer,
1304                    chain_parameter, 0);
1305            if (return_value != IFD_SUCCESS)
1306                    return return_value;
1307    
1308            sent_length += local_tx_length;
1309            tx_buffer += local_tx_length;
1310    
1311            /* we just sent the last block (0x02) or only one block was needded (0x00) */
1312            if ((0x02 == chain_parameter) || (0x00 == chain_parameter))
1313                    goto receive_block;
1314    
1315            /* read a nul block */
1316            return_value = CCID_Receive(reader_index, &local_rx_length, NULL, NULL);
1317            if (return_value != IFD_SUCCESS)
1318                    return return_value;
1319    
1320            /* size of the next block */
1321            if (tx_length - sent_length > local_tx_length)
1322            {
1323                    /* the abData field continues a command APDU and
1324                     * another block is to follow */
1325                    chain_parameter = 0x03;
1326            }
1327            else
1328            {
1329                    /* this abData field continues a command APDU and ends
1330                     * the APDU command */
1331                    chain_parameter = 0x02;
1332    
1333                    /* last (smaller) block */
1334                    local_tx_length = tx_length - sent_length;
1335            }
1336    
1337            goto send_next_block;
1338    
1339    receive_block:
1340            /* receive the APDU */
1341            received_length = 0;
1342    
1343    receive_next_block:
1344            local_rx_length = *rx_length - received_length;
1345            return_value = CCID_Receive(reader_index, &local_rx_length, rx_buffer,
1346                    &chain_parameter);
1347            if (IFD_ERROR_INSUFFICIENT_BUFFER == return_value)
1348            {
1349                    buffer_overflow = 1;
1350    
1351                    /* we continue to read all the response APDU */
1352                    return_value = IFD_SUCCESS;
1353            }
1354    
1355            if (return_value != IFD_SUCCESS)
1356                    return return_value;
1357    
1358            /* advance in the reiceiving buffer */
1359            rx_buffer += local_rx_length;
1360            received_length += local_rx_length;
1361    
1362            switch (chain_parameter)
1363            {
1364                    /* the response APDU begins and ends in this command */
1365                    case 0x00:
1366                    /* this abData field continues the response APDU and ends the response
1367                     * APDU */
1368                    case 0x02:
1369                            break;
1370    
1371                    /* the response APDU begins with this command and is to continue */
1372                    case 0x01:
1373                    /* this abData field continues the response APDU and another block is
1374                     * to follow */
1375                    case 0x03:
1376                    /* empty abData field, continuation of the command APDU is expected in
1377                     * next PC_to_RDR_XfrBlock command */
1378                    case 0x10:
1379                            /* send a nul block */
1380                            return_value = CCID_Transmit(reader_index, 0, NULL, 0, 0);
1381                            if (return_value != IFD_SUCCESS)
1382                                    return return_value;
1383    
1384                            goto receive_next_block;
1385            }
1386    
1387            *rx_length = received_length;
1388    
1389            /* generate an overflow detected by pcscd */
1390            if (buffer_overflow)
1391                    (*rx_length)++;
1392    
1393            return IFD_SUCCESS;
1394    } /* CmdXfrBlockAPDU_extended */
1395    
1396    
1397    /*****************************************************************************
1398     *
1399   *                                      CmdXfrBlockTPDU_T0   *                                      CmdXfrBlockTPDU_T0
1400   *   *
1401   ****************************************************************************/   ****************************************************************************/
1402  RESPONSECODE CmdXfrBlockTPDU_T0(int lun, int tx_length,  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
1403          unsigned char tx_buffer[], int *rx_length, unsigned char rx_buffer[])          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1404            unsigned char rx_buffer[])
1405  {  {
1406          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
1407            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1408    
1409          DEBUG_COMM2("T=0: %d bytes", tx_length);          DEBUG_COMM2("T=0: %d bytes", tx_length);
1410    
1411          return_value = CCID_Transmit(lun, tx_length, tx_buffer);          /* command length too big for CCID reader? */
1412            if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
1413            {
1414                    DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1415                                    tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
1416                    return IFD_COMMUNICATION_ERROR;
1417            }
1418    
1419            /* command length too big for CCID driver? */
1420            if (tx_length > CMD_BUF_SIZE)
1421            {
1422                    DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1423                                    tx_length, CMD_BUF_SIZE);
1424                    return IFD_COMMUNICATION_ERROR;
1425            }
1426    
1427            return_value = CCID_Transmit(reader_index, tx_length, tx_buffer, 0, 0);
1428          if (return_value != IFD_SUCCESS)          if (return_value != IFD_SUCCESS)
1429                  return return_value;                  return return_value;
1430    
1431          return CCID_Receive(lun, rx_length, rx_buffer);          return CCID_Receive(reader_index, rx_length, rx_buffer, NULL);
1432  } /* CmdXfrBlockTPDU_T0 */  } /* CmdXfrBlockTPDU_T0 */
1433    
1434    
1435  /*****************************************************************************  /*****************************************************************************
1436   *   *
1437   *                                      CmdXfrBlockTPDU_T1   *                                      T0CmdParsing
1438   *   *
1439   ****************************************************************************/   ****************************************************************************/
1440  RESPONSECODE CmdXfrBlockTPDU_T1(int lun, int tx_length,  static RESPONSECODE T0CmdParsing(unsigned char *cmd, unsigned int cmd_len,
1441          unsigned char tx_buffer[], int *rx_length, unsigned char rx_buffer[])          unsigned int *exp_len)
1442    {
1443            *exp_len = 0;
1444    
1445            /* Ref: 7816-4 Annex A */
1446            switch (cmd_len)
1447            {
1448                    case 4: /* Case 1 */
1449                            *exp_len = 2; /* SW1 and SW2 only */
1450                            break;
1451    
1452                    case 5: /* Case 2 */
1453                            if (cmd[4] != 0)
1454                                    *exp_len = cmd[4] + 2;
1455                            else
1456                                    *exp_len = 256 + 2;
1457                            break;
1458    
1459                    default: /* Case 3 */
1460                            if (cmd_len > 5 && cmd_len == (unsigned int)(cmd[4] + 5))
1461                                    *exp_len = 2; /* SW1 and SW2 only */
1462                            else
1463                                    return IFD_COMMUNICATION_ERROR; /* situation not supported */
1464                            break;
1465            }
1466    
1467            return IFD_SUCCESS;
1468    } /* T0CmdParsing */
1469    
1470    
1471    /*****************************************************************************
1472     *
1473     *                                      T0ProcACK
1474     *
1475     ****************************************************************************/
1476    static RESPONSECODE T0ProcACK(unsigned int reader_index,
1477            unsigned char **snd_buf, unsigned int *snd_len,
1478            unsigned char **rcv_buf, unsigned int *rcv_len,
1479            unsigned char **in_buf, unsigned int *in_len,
1480            unsigned int proc_len, int is_rcv)
1481  {  {
1482          RESPONSECODE return_value;          RESPONSECODE return_value;
1483          APDU_Cmd cmd;          unsigned int remain_len;
1484          APDU_Rsp rsp;          unsigned char tmp_buf[512];
1485            unsigned int ret_len;
1486    
1487            DEBUG_COMM2("Enter, is_rcv = %d", is_rcv);
1488    
1489            if (is_rcv == 1)
1490            {       /* Receiving mode */
1491                    if (*in_len > 0)
1492                    {       /* There are still available data in our buffer */
1493                            if (*in_len >= proc_len)
1494                            {
1495                                    /* We only need to get the data from our buffer */
1496                                    memcpy(*rcv_buf, *in_buf, proc_len);
1497                                    *rcv_buf += proc_len;
1498                                    *in_buf += proc_len;
1499                                    *rcv_len += proc_len;
1500                                    *in_len -= proc_len;
1501    
1502                                    return IFD_SUCCESS;
1503                            }
1504                            else
1505                            {
1506                                    /* Move all data in the input buffer to the reply buffer */
1507                                    remain_len = proc_len - *in_len;
1508                                    memcpy(*rcv_buf, *in_buf, *in_len);
1509                                    *rcv_buf += *in_len;
1510                                    *in_buf += *in_len;
1511                                    *rcv_len += *in_len;
1512                                    *in_len = 0;
1513                            }
1514                    }
1515                    else
1516                            /* There is no data in our tmp_buf,
1517                             * we have to read all data we needed */
1518                            remain_len = proc_len;
1519    
1520                    /* Read the expected data from the smartcard */
1521                    if (*in_len != 0)
1522                    {
1523                            DEBUG_CRITICAL("*in_len != 0");
1524                            return IFD_COMMUNICATION_ERROR;
1525                    }
1526    
1527                    memset(tmp_buf, 0, sizeof(tmp_buf));
1528    
1529    #ifdef O2MICRO_OZ776_PATCH
1530                    if((0 != remain_len) && (0 == (remain_len + 10) % 64))
1531            {
1532                            /* special hack to avoid a command of size modulo 64
1533                             * we send two commands instead */
1534                ret_len = 1;
1535                return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1536                if (return_value != IFD_SUCCESS)
1537                    return return_value;
1538                return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1539                if (return_value != IFD_SUCCESS)
1540                    return return_value;
1541    
1542                ret_len = remain_len - 1;
1543                return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1544                if (return_value != IFD_SUCCESS)
1545                    return return_value;
1546                return_value = CCID_Receive(reader_index, &ret_len, &tmp_buf[1],
1547                                    NULL);
1548                if (return_value != IFD_SUCCESS)
1549                    return return_value;
1550    
1551                ret_len += 1;
1552            }
1553            else
1554    #endif
1555                    {
1556                            ret_len = remain_len;
1557                            return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1558                            if (return_value != IFD_SUCCESS)
1559                                    return return_value;
1560    
1561                            return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1562                            if (return_value != IFD_SUCCESS)
1563                                    return return_value;
1564                    }
1565                    memcpy(*rcv_buf, tmp_buf, remain_len);
1566                    *rcv_buf += remain_len, *rcv_len += remain_len;
1567    
1568                    /* If ret_len != remain_len, our logic is erroneous */
1569                    if (ret_len != remain_len)
1570                    {
1571                            DEBUG_CRITICAL("ret_len != remain_len");
1572                            return IFD_COMMUNICATION_ERROR;
1573                    }
1574            }
1575            else
1576            {       /* Sending mode */
1577    
1578                    return_value = CCID_Transmit(reader_index, proc_len, *snd_buf, 1, 0);
1579                    if (return_value != IFD_SUCCESS)
1580                            return return_value;
1581    
1582                    *snd_len -= proc_len;
1583                    *snd_buf += proc_len;
1584            }
1585    
1586            DEBUG_COMM("Exit");
1587    
1588            return IFD_SUCCESS;
1589    } /* T0ProcACK */
1590    
1591    
1592          DEBUG_COMM2("T=1: %d bytes", tx_length);  /*****************************************************************************
1593     *
1594     *                                      T0ProcSW1
1595     *
1596     ****************************************************************************/
1597    static RESPONSECODE T0ProcSW1(unsigned int reader_index,
1598            unsigned char *rcv_buf, unsigned int *rcv_len,
1599            unsigned char *in_buf, unsigned int in_len)
1600    {
1601            RESPONSECODE return_value = IFD_SUCCESS;
1602            UCHAR tmp_buf[512];
1603            unsigned char *rcv_buf_tmp = rcv_buf;
1604            const unsigned int rcv_len_tmp = *rcv_len;
1605            unsigned char sw1, sw2;
1606    
1607            /* store the SW1 */
1608            sw1 = *rcv_buf = *in_buf;
1609            rcv_buf++;
1610            in_buf++;
1611            in_len--;
1612            (*rcv_len)++;
1613    
1614          /* set up command APDU */          /* store the SW2 */
1615          cmd.command = tx_buffer;          if (0 == in_len)
1616          cmd.length = tx_length;          {
1617                    return_value = CCID_Transmit(reader_index, 0, rcv_buf, 1, 0);
1618                    if (return_value != IFD_SUCCESS)
1619                            return return_value;
1620    
1621          return_value = Protocol_T1_Command(&((get_ccid_slot(lun)) -> t1), &cmd,                  in_len = 1;
                 &rsp);  
1622    
1623          if (return_value == PROTOCOL_T1_OK)                  return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1624                    if (return_value != IFD_SUCCESS)
1625                            return return_value;
1626    
1627                    in_buf = tmp_buf;
1628            }
1629            sw2 = *rcv_buf = *in_buf;
1630            rcv_buf++;
1631            in_buf++;
1632            in_len--;
1633            (*rcv_len)++;
1634    
1635            if (return_value != IFD_SUCCESS)
1636          {          {
1637                  return_value = IFD_SUCCESS;                  rcv_buf_tmp[0] = rcv_buf_tmp[1] = 0;
1638                    *rcv_len = rcv_len_tmp;
1639            }
1640    
1641            DEBUG_COMM3("Exit: SW=%02X %02X", sw1, sw2);
1642    
1643            return return_value;
1644    } /* T0ProcSW1 */
1645    
1646    
1647    /*****************************************************************************
1648     *
1649     *                                      CmdXfrBlockCHAR_T0
1650     *
1651     ****************************************************************************/
1652    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index,
1653            unsigned int snd_len, unsigned char snd_buf[], unsigned int *rcv_len,
1654            unsigned char rcv_buf[])
1655    {
1656            int is_rcv;
1657            unsigned char cmd[5];
1658            unsigned char tmp_buf[512];
1659            unsigned int exp_len, in_len;
1660            unsigned char ins, *in_buf;
1661            RESPONSECODE return_value = IFD_SUCCESS;
1662            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1663    
1664            DEBUG_COMM2("T=0: %d bytes", snd_len);
1665    
1666            if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
1667            {
1668                    unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
1669    
1670                    /* Command to send to the smart card (must be 5 bytes) */
1671                    memset(cmd, 0, sizeof(cmd));
1672                    if (snd_len == 4)
1673                    {
1674                            memcpy(cmd, snd_buf, 4);
1675                            snd_buf += 4;
1676                            snd_len -= 4;
1677                    }
1678                    else
1679                    {
1680                            memcpy(cmd, snd_buf, 5);
1681                            snd_buf += 5;
1682                            snd_len -= 5;
1683                    }
1684    
1685                    /* at most 5 bytes */
1686                    return_value = CCID_Transmit(reader_index, 5, cmd, 0, 0);
1687                    if (return_value != IFD_SUCCESS)
1688                            return return_value;
1689    
1690                    /* wait for ready */
1691                    return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1692                    if (return_value != IFD_SUCCESS)
1693                            return return_value;
1694    
1695                    if ((0x20 != pcbuffer[0]) && (snd_len > 0))
1696                    {
1697                            /* continue sending the APDU */
1698                            return_value = CCID_Transmit(reader_index, snd_len, snd_buf, 0, 0);
1699                            if (return_value != IFD_SUCCESS)
1700                                    return return_value;
1701                    }
1702                    else
1703                    {
1704                            if ((0x20 == pcbuffer[0]) && (*rcv_len > 2))
1705                                    /* we will just read SW1-SW2 */
1706                                    *rcv_len = 2;
1707    
1708                            return_value = CCID_Receive(reader_index, rcv_len, rcv_buf, NULL);
1709                            if (return_value != IFD_SUCCESS)
1710                                    DEBUG_CRITICAL("CCID_Receive failed");
1711    
1712                            return return_value;
1713                    }
1714    
1715                  /* copy the response */                  /* wait for ready */
1716                  memcpy(rx_buffer, rsp.response, rsp.length);                  return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1717                    if (return_value != IFD_SUCCESS)
1718                            return return_value;
1719    
1720                  /* free the allocated response buffer */                  if ((0x20 == pcbuffer[0]) && (*rcv_len > 2))
1721                  free(rsp.response);                          /* we will just read SW1-SW2 */
1722                            *rcv_len = 2;
1723    
1724                    /* read SW1-SW2 */
1725                    return_value = CCID_Receive(reader_index, rcv_len, rcv_buf, NULL);
1726                    if (return_value != IFD_SUCCESS)
1727                            DEBUG_CRITICAL("CCID_Receive failed");
1728    
1729                  *rx_length = rsp.length;                  return return_value;
1730            }
1731    
1732            in_buf = tmp_buf;
1733            in_len = 0;
1734            *rcv_len = 0;
1735    
1736            return_value = T0CmdParsing(snd_buf, snd_len, &exp_len);
1737            if (return_value != IFD_SUCCESS)
1738            {
1739                    DEBUG_CRITICAL("T0CmdParsing failed");
1740                    return IFD_COMMUNICATION_ERROR;
1741            }
1742    
1743            if (snd_len == 5 || snd_len == 4)
1744                    is_rcv = 1;
1745            else
1746                    is_rcv = 0;
1747    
1748            /* Command to send to the smart card (must be 5 bytes, from 7816 p.15) */
1749            memset(cmd, 0, sizeof(cmd));
1750            if (snd_len == 4)
1751            {
1752                    memcpy(cmd, snd_buf, 4);
1753                    snd_buf += 4;
1754                    snd_len -= 4;
1755          }          }
1756          else          else
1757            {
1758                    memcpy(cmd, snd_buf, 5);
1759                    snd_buf += 5;
1760                    snd_len -= 5;
1761            }
1762    
1763            /* Make sure this is a valid command by checking the INS field */
1764            ins = cmd[1];
1765            if ((ins & 0xF0) == 0x60 ||     /* 7816-3 8.3.2 */
1766                    (ins & 0xF0) == 0x90)
1767            {
1768                    DEBUG_CRITICAL2("fatal: INS (0x%02X) = 0x6X or 0x9X", ins);
1769                    return IFD_COMMUNICATION_ERROR;
1770            }
1771    
1772            return_value = CCID_Transmit(reader_index, 5, cmd, 1, 0);
1773            if (return_value != IFD_SUCCESS)
1774                    return return_value;
1775    
1776            while (1)
1777            {
1778                    if (in_len == 0)
1779                    {
1780                            in_len = 1;
1781                            return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1782                            if (return_value != IFD_SUCCESS)
1783                            {
1784                                    DEBUG_CRITICAL("CCID_Receive failed");
1785                                    return return_value;
1786                            }
1787                            in_buf = tmp_buf;
1788                    }
1789                    if (in_len == 0)
1790                    {
1791                            /* Suppose we should be able to get data.
1792                             * If not, error. Set the time-out error */
1793                            DEBUG_CRITICAL("error: in_len = 0");
1794                            return IFD_RESPONSE_TIMEOUT;
1795                    }
1796    
1797                    /* Start to process the procedure bytes */
1798                    if (*in_buf == 0x60)
1799                    {
1800                            in_len = 0;
1801                            return_value = CCID_Transmit(reader_index, 0, cmd, 1, 0);
1802    
1803                            if (return_value != IFD_SUCCESS)
1804                                    return return_value;
1805    
1806                            continue;
1807                    }
1808                    else if (*in_buf == ins || *in_buf == (ins ^ 0x01))
1809                    {
1810                            /* ACK => To transfer all remaining data bytes */
1811                            in_buf++, in_len--;
1812                            if (is_rcv)
1813                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1814                                            &rcv_buf, rcv_len, &in_buf, &in_len, exp_len - *rcv_len, 1);
1815                            else
1816                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1817                                            &rcv_buf, rcv_len, &in_buf, &in_len, snd_len, 0);
1818    
1819                            if (*rcv_len == exp_len)
1820                                    return return_value;
1821    
1822                            continue;
1823                    }
1824                    else if (*in_buf == (ins ^ 0xFF) || *in_buf == (ins ^ 0xFE))
1825                    {
1826                            /* ACK => To transfer 1 remaining bytes */
1827                            in_buf++, in_len--;
1828                            return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1829                                    &rcv_buf, rcv_len, &in_buf, &in_len, 1, is_rcv);
1830    
1831                            if (return_value != IFD_SUCCESS)
1832                                    return return_value;
1833    
1834                            continue;
1835                    }
1836                    else if ((*in_buf & 0xF0) == 0x60 || (*in_buf & 0xF0) == 0x90)
1837                            /* SW1 */
1838                            return T0ProcSW1(reader_index, rcv_buf, rcv_len, in_buf, in_len);
1839    
1840                    /* Error, unrecognized situation found */
1841                    DEBUG_CRITICAL2("Unrecognized Procedure byte (0x%02X) found!", *in_buf);
1842                    return return_value;
1843            }
1844    
1845            return return_value;
1846    } /* CmdXfrBlockCHAR_T0 */
1847    
1848    
1849    /*****************************************************************************
1850     *
1851     *                                      CmdXfrBlockTPDU_T1
1852     *
1853     ****************************************************************************/
1854    static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
1855            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1856            unsigned char rx_buffer[])
1857    {
1858            RESPONSECODE return_value = IFD_SUCCESS;
1859            int ret;
1860    
1861            DEBUG_COMM3("T=1: %d and %d bytes", tx_length, *rx_length);
1862    
1863            ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
1864                    tx_buffer, tx_length, rx_buffer, *rx_length);
1865    
1866            if (ret < 0)
1867                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
1868            else
1869                    *rx_length = ret;
1870    
1871          return return_value;          return return_value;
1872  } /* CmdXfrBlockTPDU_T1 */  } /* CmdXfrBlockTPDU_T1 */
# Line 433  RESPONSECODE CmdXfrBlockTPDU_T1(int lun, Line 1874  RESPONSECODE CmdXfrBlockTPDU_T1(int lun,
1874    
1875  /*****************************************************************************  /*****************************************************************************
1876   *   *
1877     *                                      SetParameters
1878     *
1879     ****************************************************************************/
1880    RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
1881            unsigned int length, unsigned char buffer[])
1882    {
1883            unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
1884            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1885    
1886            DEBUG_COMM2("length: %d bytes", length);
1887    
1888            cmd[0] = 0x61; /* SetParameters */
1889            i2dw(length, cmd+1);    /* APDU length */
1890            cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
1891            cmd[6] = (*ccid_descriptor->pbSeq)++;
1892            cmd[7] = protocol;      /* bProtocolNum */
1893            cmd[8] = cmd[9] = 0; /* RFU */
1894    
1895            /* check that the command is not too large */
1896            if (length > CMD_BUF_SIZE)
1897                    return IFD_NOT_SUPPORTED;
1898    
1899            memcpy(cmd+10, buffer, length);
1900    
1901            if (WritePort(reader_index, 10+length, cmd) != STATUS_SUCCESS)
1902                    return IFD_COMMUNICATION_ERROR;
1903    
1904            length = sizeof(cmd);
1905            if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
1906                    return IFD_COMMUNICATION_ERROR;
1907    
1908            if (length < STATUS_OFFSET+1)
1909            {
1910                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
1911                    return IFD_COMMUNICATION_ERROR;
1912            }
1913    
1914            if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1915            {
1916                    ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
1917                    if (0x00 == cmd[ERROR_OFFSET])  /* command not supported */
1918                            return IFD_NOT_SUPPORTED;
1919                    else
1920                            if ((cmd[ERROR_OFFSET] >= 1) && (cmd[ERROR_OFFSET] <= 127))
1921                                    /* a parameter is not changeable */
1922                                    return IFD_SUCCESS;
1923                            else
1924                                    return IFD_COMMUNICATION_ERROR;
1925            }
1926    
1927            return IFD_SUCCESS;
1928    } /* SetParameters */
1929    
1930    
1931    /*****************************************************************************
1932     *
1933     *                                      isCharLevel
1934     *
1935     ****************************************************************************/
1936    int isCharLevel(int reader_index)
1937    {
1938            return CCID_CLASS_CHARACTER == (get_ccid_descriptor(reader_index)->dwFeatures & CCID_CLASS_EXCHANGE_MASK);
1939    } /* isCharLevel */
1940    
1941    
1942    /*****************************************************************************
1943     *
1944   *                                      i2dw   *                                      i2dw
1945   *   *
1946   ****************************************************************************/   ****************************************************************************/
1947  void i2dw(int value, unsigned char buffer[])  static void i2dw(int value, unsigned char buffer[])
1948  {  {
1949          buffer[0] = value & 0xFF;          buffer[0] = value & 0xFF;
1950          buffer[1] = (value >> 8) & 0xFF;          buffer[1] = (value >> 8) & 0xFF;

Legend:
Removed from v.614  
changed lines
  Added in v.2472

  ViewVC Help
Powered by ViewVC 1.1.5