source: trunk/csctapi/protocol_t0.c @ 8

Last change on this file since 8 was 8, checked in by smurzch2, 11 years ago

Start repository for OSCam (Open Source Cam)

The start is from the MpCS source code. Thanks a lot to the authors for this
great sources.

File size: 26.3 KB
Line 
1/*
2    protocol_t0.c
3    Handling of ISO 7816 T=0 protocol
4
5    This file is part of the Unix driver for Towitoko smartcard readers
6    Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>
7
8    This version is modified by doz21 to work in a special manner ;)
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23*/
24
25#include "defines.h"
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <time.h>
30
31
32#include "protocol_t0.h"
33#include "atr.h"
34
35/*
36 * Not exported constants definition
37 */
38
39#define PROTOCOL_T0_MAX_NULLS          200
40#define PROTOCOL_T0_DEFAULT_WI         10
41#define PROTOCOL_T0_MAX_SHORT_COMMAND  260
42#define PROTOCOL_T0_MAX_SHORT_RESPONSE 258
43
44#define PROTOCOL_T14_MAX_NULLS          200
45#define PROTOCOL_T14_DEFAULT_WI         10
46#define PROTOCOL_T14_MAX_SHORT_COMMAND  260
47#define PROTOCOL_T14_MAX_SHORT_RESPONSE 258
48
49/*
50 * Not exported functions declaration
51 */
52
53static void Protocol_T0_Clear (Protocol_T0 * t0);
54static void Protocol_T14_Clear (Protocol_T14 * t14);
55
56static int Protocol_T0_Case1 (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
57
58static int Protocol_T0_Case2S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
59static int Protocol_T14_Case2S (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp);
60
61static int Protocol_T0_Case3S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
62static int Protocol_T14_Case3S (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp);
63
64static int Protocol_T0_Case4S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
65
66static int Protocol_T0_Case2E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
67
68static int Protocol_T0_Case3E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
69
70static int Protocol_T0_Case4E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
71
72static int Protocol_T0_ExchangeTPDU (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp);
73static int Protocol_T14_ExchangeTPDU (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp);
74
75/*
76 * Exproted funtions definition
77 */
78
79Protocol_T0 * Protocol_T0_New (void)
80{
81    Protocol_T0 *t0;
82   
83    t0 = (Protocol_T0 *) malloc (sizeof (Protocol_T0));
84   
85    if (t0 != NULL)
86        Protocol_T0_Clear (t0);
87   
88    return t0;
89}
90
91Protocol_T14 * Protocol_T14_New (void)
92{
93    Protocol_T14 *t14;
94   
95    t14 = (Protocol_T14 *) malloc (sizeof (Protocol_T14));
96   
97    if (t14 != NULL)
98        Protocol_T14_Clear (t14);
99   
100    return t14;
101}
102
103int Protocol_T0_Init (Protocol_T0 * t0, ICC_Async * icc, PPS_ProtocolParameters * params)
104{
105    ICC_Async_Timings timings;
106    BYTE wi;
107#ifndef PROTOCOL_T0_USE_DEFAULT_TIMINGS
108    ATR *atr = ICC_Async_GetAtr (icc);
109#endif
110   
111    /* Set ICC */
112    t0->icc = icc;
113   
114    /* Integer value WI  = TC2, by default 10 */
115#ifndef PROTOCOL_T0_USE_DEFAULT_TIMINGS
116    if (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TC, &(wi)) != ATR_OK)
117#endif
118    wi = PROTOCOL_T0_DEFAULT_WI;
119   
120    /* WWT = 960 * WI * (Fi / f) * 1000 milliseconds */
121    t0->wwt = (long unsigned int) (960 * wi * (params->f / ICC_Async_GetClockRate (t0->icc)) * 1000);
122   
123    /* Set timings */
124    ICC_Async_GetTimings (t0->icc, &timings);
125   
126    timings.block_timeout = t0->wwt;
127    timings.char_timeout = t0->wwt;
128   
129    ICC_Async_SetTimings (t0->icc, &timings);
130   
131#ifdef DEBUG_PROTOCOL
132    printf ("Protocol: T=0: WWT=%d\n", (int)(t0->wwt));
133#endif
134   
135    return PROTOCOL_T0_OK;
136}
137
138int Protocol_T14_Init (Protocol_T14 * t14, ICC_Async * icc, PPS_ProtocolParameters * params)
139{
140    ICC_Async_Timings timings;
141    BYTE wi;
142#ifndef PROTOCOL_T14_USE_DEFAULT_TIMINGS
143    ATR *atr = ICC_Async_GetAtr (icc);
144#endif
145   
146    /* Set ICC */
147    t14->icc = icc;
148   
149    /* Integer value WI  = TC2, by default 10 */
150#ifndef PROTOCOL_T14_USE_DEFAULT_TIMINGS
151    if (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TC, &(wi)) != ATR_OK)
152#endif
153    wi = PROTOCOL_T14_DEFAULT_WI;
154   
155    /* WWT = 960 * WI * (Fi / f) * 1000 milliseconds */
156    t14->wwt = (long unsigned int) (960 * wi * (params->f / ICC_Async_GetClockRate (t14->icc)) * 1000);
157    t14->wwt >>= 1;
158   
159    /* Set timings */
160    ICC_Async_GetTimings (t14->icc, &timings);
161   
162    timings.block_timeout = t14->wwt;
163    timings.char_timeout = t14->wwt;
164   
165    ICC_Async_SetTimings (t14->icc, &timings);
166   
167#ifdef DEBUG_PROTOCOL
168    printf ("Protocol: T=14: WWT=%d\n", (int)(t14->wwt));
169#endif
170   
171    return PROTOCOL_T14_OK;
172}
173
174int Protocol_T0_Command (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
175{
176    int cmd_case, ret;
177   
178    cmd_case = APDU_Cmd_Case (cmd);
179   
180#ifdef DEBUG_PROTOCOL
181    if (cmd_case != APDU_MALFORMED)
182        printf ("Protocol: T=0 Case %d %s\n", (cmd_case & 0x0F), APDU_CASE_IS_EXTENDED (cmd_case)? "extended": "short");
183#endif
184   
185    if (cmd_case == APDU_CASE_1)
186        ret = Protocol_T0_Case1 (t0, cmd, rsp);
187    else if (cmd_case == APDU_CASE_2S)
188        ret = Protocol_T0_Case2S (t0, cmd, rsp);
189    else if (cmd_case == APDU_CASE_3S)
190        ret = Protocol_T0_Case3S (t0, cmd, rsp);
191    else if (cmd_case == APDU_CASE_4S)
192        ret = Protocol_T0_Case4S (t0, cmd, rsp);
193    else if (cmd_case == APDU_CASE_2E)
194        ret = Protocol_T0_Case2E (t0, cmd, rsp);
195    else if (cmd_case == APDU_CASE_3E)
196        ret = Protocol_T0_Case3E (t0, cmd, rsp);
197    else if (cmd_case == APDU_CASE_4E)
198        ret = Protocol_T0_Case4E (t0, cmd, rsp);
199    else
200    {
201#ifdef DEBUG_PROTOCOL
202        printf ("Protocol: T=0: Invalid APDU\n");
203#endif
204        ret = PROTOCOL_T0_ERROR;
205    }
206   
207    return ret;
208}
209
210int Protocol_T14_Command (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp)
211{
212    int cmd_case, ret;
213       
214    cmd_case = APDU_Cmd_Case (cmd);
215   
216#ifdef DEBUG_PROTOCOL
217    if (cmd_case != APDU_MALFORMED)
218        printf ("Protocol: T=14 Case %d %s\n", (cmd_case & 0x0F), APDU_CASE_IS_EXTENDED (cmd_case)? "extended": "short");
219#endif
220   
221    if (cmd_case == APDU_CASE_2S)
222    {
223        ret = Protocol_T14_Case2S (t14, cmd, rsp);
224    }
225    else if (cmd_case == APDU_CASE_3S)
226    {
227        ret = Protocol_T14_Case3S (t14, cmd, rsp);
228    }
229    else
230    {
231#ifdef DEBUG_PROTOCOL
232        printf ("Protocol: T=14: Invalid APDU\n");
233#endif
234    ret = PROTOCOL_T14_ERROR;
235    }
236   
237    return ret;
238}
239
240int Protocol_T0_Close (Protocol_T0 * t0)
241{
242    Protocol_T0_Clear (t0);
243   
244    return PROTOCOL_T0_OK;
245}
246
247int Protocol_T14_Close (Protocol_T14 * t14)
248{
249    Protocol_T14_Clear (t14);
250   
251    return PROTOCOL_T14_OK;
252}
253
254void Protocol_T0_Delete (Protocol_T0 * t0)
255{
256    free (t0);
257}
258
259void Protocol_T14_Delete (Protocol_T14 * t14)
260{
261    free (t14);
262}
263
264/*
265 * Not exported functions definition
266 */
267
268static int Protocol_T0_Case1 (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
269{
270    int ret;
271    BYTE buffer[5];
272    APDU_Cmd *tpdu_cmd;
273   
274    /* Map command APDU onto TPDU */
275    memcpy (buffer, APDU_Cmd_Raw (cmd), 4);
276    buffer[4] = 0x00;
277   
278    tpdu_cmd = APDU_Cmd_New (buffer, 5);
279   
280    /* Send command TPDU */
281    ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, rsp);
282   
283    /* Delete command TPDU */
284    APDU_Cmd_Delete (tpdu_cmd);
285   
286    return ret;
287}
288
289
290static int Protocol_T0_Case2S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
291{
292    int ret;
293   
294    /* Send command TPDU */
295    ret = Protocol_T0_ExchangeTPDU (t0, cmd, rsp);
296   
297    return ret;
298}
299
300static int Protocol_T14_Case2S (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp)
301{
302    int ret;
303   
304    /* Send command TPDU */
305    ret = Protocol_T14_ExchangeTPDU (t14, cmd, rsp);
306   
307    return ret;
308}
309
310static int Protocol_T0_Case3S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
311{
312    int ret;
313    APDU_Rsp *tpdu_rsp;
314#ifdef PROTOCOL_T0_ISO
315    BYTE buffer[5];
316    APDU_Cmd *tpdu_cmd;
317#endif
318   
319    /* Send command TPDU */
320    ret = Protocol_T0_ExchangeTPDU (t0, cmd, (&tpdu_rsp));
321   
322    if (ret == PROTOCOL_T0_OK)
323    {
324#ifdef PROTOCOL_T0_ISO
325        /*  Le definitely not accepted */
326        if (APDU_Rsp_SW1 (tpdu_rsp) == 0x67)
327        {
328            /* Map response APDU onto TPDU without change */
329            (*rsp) = tpdu_rsp;
330        }
331        else if (APDU_Rsp_SW1 (tpdu_rsp) == 0x6C) /* Le not accepted, La indicated */
332        {
333            /* Map command APDU onto TPDU */
334            memcpy (buffer, APDU_Cmd_Raw (cmd), 4);
335            buffer[4] = APDU_Rsp_SW2 (tpdu_rsp);
336           
337            tpdu_cmd = APDU_Cmd_New (buffer, 5);
338           
339            /* Delete response TPDU */
340            APDU_Rsp_Delete (tpdu_rsp);
341           
342            /* Re-issue command TPDU */
343            ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, rsp);
344           
345            /* Delete command TPDU */
346            APDU_Cmd_Delete (tpdu_cmd);
347           
348            if (ret == PROTOCOL_T0_OK)
349            {
350                if (APDU_Rsp_DataLen ((*rsp)) > APDU_Cmd_Le (cmd))
351                {
352                    /* Map response APDU onto TPDU */
353                    APDU_Rsp_TruncateData ((*rsp), APDU_Cmd_Le (cmd));
354                }
355            }
356        }
357        else if (APDU_Rsp_SW1 (tpdu_rsp) == 0x61) /* Command processed, Lx indicated */
358        {
359            /* MAP response TPDU onto APDU */
360            (*rsp) = tpdu_rsp;
361           
362            /* Prepare Get Response TPDU */
363            buffer[0] = APDU_Cmd_Cla (cmd);
364            buffer[1] = 0xC0;
365            buffer[2] = 0x00;
366            buffer[3] = 0x00;
367   
368            do
369            {
370                /* Issue Get Response command TPDU */
371                buffer[4] = APDU_Rsp_SW2 (tpdu_rsp);
372                tpdu_cmd = APDU_Cmd_New (buffer, 5);
373               
374                ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
375               
376                /* Delete command TPDU */
377                APDU_Cmd_Delete (tpdu_cmd);
378               
379                if (ret == PROTOCOL_T0_OK)
380                {
381                    /* Append response TPDU to APDU  */
382                    if (APDU_Rsp_AppendData ((*rsp), tpdu_rsp) != APDU_OK)
383                        ret = PROTOCOL_T0_ERROR;
384                   
385                    /* Delete response TPDU */
386                    APDU_Rsp_Delete (tpdu_rsp);
387                }
388            }
389            while ((ret == PROTOCOL_T0_OK) && (APDU_Rsp_SW1 (*rsp) == 0x61));
390   
391            if (ret == PROTOCOL_T0_OK)
392            {
393                if (APDU_Rsp_DataLen ((*rsp)) > APDU_Cmd_Le (cmd))
394                {
395                    /* Map response APDU onto TPDU */
396                    APDU_Rsp_TruncateData ((*rsp), APDU_Cmd_Le (cmd));
397                }
398            }
399        }   
400        else /* Le accepted */
401        {
402            /* Map response TPDU onto APDU without change */
403            (*rsp) = tpdu_rsp;
404        }
405#else
406    (*rsp) = tpdu_rsp;
407#endif
408    }
409   
410    return ret;
411}
412
413static int Protocol_T14_Case3S (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp)
414{
415    int ret;
416   
417    /* Send command TPDU */
418    ret = Protocol_T14_ExchangeTPDU (t14, cmd, rsp);
419   
420    return ret;
421}
422
423static int Protocol_T0_Case4S (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
424{
425    int ret;
426    BYTE buffer[PROTOCOL_T0_MAX_SHORT_COMMAND];
427    APDU_Cmd *tpdu_cmd;
428    APDU_Rsp *tpdu_rsp;
429   
430    /* Map command APDU onto TPDU */
431    memcpy (buffer, APDU_Cmd_Raw (cmd), APDU_Cmd_RawLen (cmd) - 1);
432   
433    tpdu_cmd = APDU_Cmd_New (buffer, APDU_Cmd_RawLen (cmd) - 1);
434   
435    /* Send command TPDU */
436    ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
437   
438    /* Delete command TPDU */
439    APDU_Cmd_Delete (tpdu_cmd);
440   
441    if (ret == PROTOCOL_T0_OK)
442    {
443#ifdef PROTOCOL_T0_ISO
444        /* Command accepted with information added */
445        if (APDU_Rsp_SW1 (tpdu_rsp) == 0x61)
446        {
447            /* Prepare Get Reponse command TPDU */
448            buffer[0] = APDU_Cmd_Cla (cmd);
449            buffer[1] = 0xC0;
450            buffer[2] = 0x00;
451            buffer[3] = 0x00;
452           
453            if (APDU_Rsp_SW2 (tpdu_rsp) == 0x00)
454                buffer[4] = (BYTE) APDU_Cmd_Le (cmd);
455            else
456                buffer[4] = MIN (APDU_Cmd_Le (cmd), APDU_Rsp_SW2 (tpdu_rsp));
457           
458            tpdu_cmd = APDU_Cmd_New (buffer, 5);
459           
460            /* Delete response TPDU */
461            APDU_Rsp_Delete (tpdu_rsp);
462           
463            /* Issue Get Reponse command */
464            ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, rsp);
465           
466            /* Delete command TPDU */
467            APDU_Cmd_Delete (tpdu_cmd);
468        }   
469        else if ((APDU_Rsp_SW1 (tpdu_rsp) & 0xF0) == 0x60) /* Command not accepted */
470        {
471            /* Map response TPDU onto APDU without change */
472            (*rsp) = tpdu_rsp;
473        }
474        else /* Command accepted */
475        {
476            /* Delete response TPDU */
477            APDU_Rsp_Delete (tpdu_rsp);
478           
479            /* Prepare Get Reponse TPDU */
480            buffer[0] = APDU_Cmd_Cla (cmd);
481            buffer[1] = 0xC0;
482            buffer[2] = 0x00;
483            buffer[3] = 0x00;
484            buffer[4] = (BYTE) APDU_Cmd_Le (cmd);
485           
486            tpdu_cmd = APDU_Cmd_New (buffer, 5);
487           
488            /* Issue Get Reponse command TPDU */
489            ret = Protocol_T0_Case3S (t0, tpdu_cmd, rsp);
490           
491            /* Delete command TPDU */
492            APDU_Cmd_Delete (tpdu_cmd);
493        }
494#else
495        (*rsp) = tpdu_rsp;
496#endif
497    }
498   
499    return ret;
500}
501
502
503static int Protocol_T0_Case2E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
504{
505    int ret = PROTOCOL_T0_OK, i;
506    BYTE buffer[PROTOCOL_T0_MAX_SHORT_COMMAND];
507    APDU_Cmd *tpdu_cmd;
508    APDU_Rsp *tpdu_rsp;
509   
510    if (APDU_Cmd_Lc (cmd) < 256)
511    {
512        /* MAP APDU onto command TPDU */
513        buffer[0] = APDU_Cmd_Cla (cmd);
514        buffer[1] = APDU_Cmd_Ins (cmd);
515        buffer[2] = APDU_Cmd_P1 (cmd);
516        buffer[3] = APDU_Cmd_P2 (cmd);
517        buffer[4] = (BYTE) APDU_Cmd_Lc (cmd);
518       
519        memcpy (buffer + 5, APDU_Cmd_Data (cmd), buffer[4]);
520       
521        tpdu_cmd = APDU_Cmd_New (buffer, buffer[4] + 5);
522       
523        /* Send command TPDU */
524        ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, rsp);
525       
526        /* Delete command TPDU */
527        APDU_Cmd_Delete (tpdu_cmd);
528    }
529    else
530    {
531        /* Prepare envelope TPDU */
532        buffer[0] = APDU_Cmd_Cla (cmd);
533        buffer[1] = 0xC2;
534        buffer[2] = 0x00;
535        buffer[3] = 0x00;
536       
537        for (i = 0; i < APDU_Cmd_RawLen (cmd); i += buffer[4])
538        {
539            /* Create envelope command TPDU */
540            buffer[4] = MIN (255, APDU_Cmd_RawLen (cmd) - i);
541            memcpy (buffer + 5, APDU_Cmd_Raw (cmd) + i, buffer[4]);
542           
543            tpdu_cmd = APDU_Cmd_New (buffer, buffer[4] + 5);
544           
545            /* Send envelope command TPDU */
546            ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
547           
548            /* Delete command TPDU */
549            APDU_Cmd_Delete (tpdu_cmd);
550           
551            if (ret == PROTOCOL_T0_OK)
552            {
553                /*  Card does support envelope command */
554                if (APDU_Rsp_SW1 (tpdu_rsp) == 0x90)
555                {
556                    /* This is not the last segment */
557                    if (buffer[4] + i < APDU_Cmd_RawLen (cmd))
558                    {
559                        /* Delete response TPDU */
560                        APDU_Rsp_Delete (tpdu_rsp);
561                    }
562                    else
563                    {
564                        /* Map response TPDU onto APDU */
565                        (*rsp) = tpdu_rsp;
566                    }
567                }   
568                else /* Card does not support envelope command or error */
569                {
570                    /* Map response tpdu onto APDU without change */
571                    (*rsp) = tpdu_rsp;
572                    break;
573                }
574            }
575            else
576            {
577                break;
578            }
579        }
580    }
581   
582    return ret;
583}
584
585
586static int Protocol_T0_Case3E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
587{
588    int ret;
589    BYTE buffer[5];
590    APDU_Cmd *tpdu_cmd;
591    APDU_Rsp *tpdu_rsp;
592    long Lm, Lx;
593   
594    if (APDU_Cmd_Le (cmd) <= 256)
595    {
596        /* Map APDU onto command TPDU */
597        buffer[0] = APDU_Cmd_Cla (cmd);
598        buffer[1] = APDU_Cmd_Ins (cmd);
599        buffer[2] = APDU_Cmd_P1 (cmd);
600        buffer[3] = APDU_Cmd_P2 (cmd);
601        buffer[4] = (BYTE) APDU_Cmd_Le (cmd);
602       
603        tpdu_cmd = APDU_Cmd_New (buffer, 5);
604       
605        /* Send command TPDU */
606        ret = Protocol_T0_Case3S (t0, tpdu_cmd, rsp);
607       
608        /* Delete command TPDU */
609        APDU_Cmd_Delete (tpdu_cmd);
610    }
611    else
612    {
613        /* Map APDU onto command TPDU */
614        buffer[0] = APDU_Cmd_Cla (cmd);
615        buffer[1] = APDU_Cmd_Ins (cmd);
616        buffer[2] = APDU_Cmd_P1 (cmd);
617        buffer[3] = APDU_Cmd_P2 (cmd);
618        buffer[4] = 0x00;
619       
620        tpdu_cmd = APDU_Cmd_New (buffer, 5);
621       
622        /* Send command TPDU */
623        ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
624       
625        /* Delete command TPDU */
626        APDU_Cmd_Delete (tpdu_cmd);
627       
628        if (ret == PROTOCOL_T0_OK)
629        {
630            /*  Le definitely not accepted */
631            if (APDU_Rsp_SW1 (tpdu_rsp) == 0x67)
632            {
633                /* Map response APDU onto TPDU without change */
634                (*rsp) = tpdu_rsp;
635            }       
636            else if (APDU_Rsp_SW1 (tpdu_rsp) == 0x6C) /* Le not accepted, La indicated */
637            {
638                /* Map command APDU onto TPDU */
639                memcpy (buffer, APDU_Cmd_Raw (cmd), 4);
640                buffer[4] = APDU_Rsp_SW2 (tpdu_rsp);
641               
642                tpdu_cmd = APDU_Cmd_New (buffer, 5);
643               
644                /* Delete response TPDU */
645                APDU_Rsp_Delete (tpdu_rsp);
646               
647                /* Re-issue command TPDU */
648                ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, rsp);
649               
650                /* Delete command TPDU */
651                APDU_Cmd_Delete (tpdu_cmd);
652            }
653            else if (APDU_Rsp_SW1 (tpdu_rsp) == 0x61) /* Command processed, Lx indicated */
654            {
655                /* Map response TPDU onto APDU */
656                (*rsp) = tpdu_rsp;
657               
658                Lx = (APDU_Rsp_SW2 (tpdu_rsp) == 0x00) ? 256 : APDU_Rsp_SW2 (tpdu_rsp);
659                Lm = APDU_Cmd_Le (cmd) - APDU_Rsp_DataLen (*rsp);
660               
661                /* Prepare Get Response TPDU */
662                buffer[0] = APDU_Cmd_Cla (cmd);
663                buffer[1] = 0xC0;
664                buffer[2] = 0x00;
665                buffer[3] = 0x00;
666               
667                while (Lm > 0)
668                {
669                    buffer[4] = (BYTE) MIN (Lm, Lx);
670                   
671                    tpdu_cmd = APDU_Cmd_New (buffer, 5);
672                   
673                    /* Issue Get Response command TPDU */
674                    ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
675                   
676                    /* Delete command TPDU */
677                    APDU_Cmd_Delete (tpdu_cmd);
678                   
679                    if (ret == PROTOCOL_T0_OK)
680                    {
681                        /* Append response TPDU to APDU  */
682                        if (APDU_Rsp_AppendData ((*rsp), tpdu_rsp) != APDU_OK)
683                        {
684                            ret = PROTOCOL_T0_ERROR;
685                            APDU_Rsp_Delete (tpdu_rsp);
686                            break;
687                        }
688                       
689                        /* Delete response TPDU */
690                        APDU_Rsp_Delete (tpdu_rsp);
691                    }
692                    else
693                    {
694                        break;
695                    }
696                   
697                    Lm = APDU_Cmd_Le (cmd) - APDU_Rsp_DataLen (*rsp);
698                }/* Lm == 0 */
699            } 
700            else /* Le accepted: card has no more than 265 bytes or does not support Get Response */
701            {
702                /* Map response TPDU onto APDU without change */
703                (*rsp) = tpdu_rsp;
704            }
705        }
706    }
707   
708    return ret;
709}
710
711
712static int Protocol_T0_Case4E (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
713{
714    int ret;
715    BYTE buffer[PROTOCOL_T0_MAX_SHORT_COMMAND];
716    APDU_Cmd *tpdu_cmd, *gr_cmd;
717    APDU_Rsp *tpdu_rsp;
718    long Le;
719   
720    /* 4E1 */
721    if (APDU_Cmd_Lc (cmd) < 256)
722    {
723        /* Map APDU onto command TPDU */
724        buffer[0] = APDU_Cmd_Cla (cmd);
725        buffer[1] = APDU_Cmd_Ins (cmd);
726        buffer[2] = APDU_Cmd_P1 (cmd);
727        buffer[3] = APDU_Cmd_P2 (cmd);
728        buffer[4] = (BYTE) APDU_Cmd_Lc (cmd);
729        memcpy (buffer + 5, APDU_Cmd_Data (cmd), buffer[4]);
730       
731        tpdu_cmd = APDU_Cmd_New (buffer, buffer[4] + 5);
732       
733        /* Send command TPDU */
734        ret = Protocol_T0_ExchangeTPDU (t0, tpdu_cmd, (&tpdu_rsp));
735       
736        /* Delete command TPDU */
737        APDU_Cmd_Delete (tpdu_cmd);
738    }
739    else /* 4E2 */
740    {
741        ret = Protocol_T0_Case2E (t0, cmd, (&tpdu_rsp));
742    }
743   
744    /* 4E1 a) b) and c) */
745    if (ret == PROTOCOL_T0_OK)
746    {
747        if (APDU_Rsp_SW1 (tpdu_rsp) == 0x61)
748        {
749            /* Lm == (Le - APDU_Rsp_RawLen (tpdu_rsp)) == 0 */
750           
751            if (APDU_Rsp_SW2 (tpdu_rsp) != 0x00)
752                Le = MIN(APDU_Rsp_SW2 (tpdu_rsp), APDU_Cmd_Le(cmd));
753            else
754                Le = APDU_Cmd_Le (cmd); 
755           
756            /* Delete response TPDU */
757            APDU_Rsp_Delete (tpdu_rsp);
758           
759            /* Prepare extended Get Response APDU command */
760            buffer[0] = APDU_Cmd_Cla (cmd);
761            buffer[1] = 0xC0;
762            buffer[2] = 0x00;
763            buffer[3] = 0x00;
764            buffer[4] = 0x00;     /* B1 = 0x00 */
765            buffer[5] = (BYTE) (Le >> 8);  /* B2 = BL-1 */
766            buffer[6] = (BYTE) (Le & 0x00FF);      /* B3 = BL */
767           
768            gr_cmd = APDU_Cmd_New (buffer, 7);
769           
770            /* Issue Case 3E get response command */ 
771            ret = Protocol_T0_Case3E (t0, gr_cmd, rsp);
772           
773            /* Delete Get Response command APDU */
774            APDU_Cmd_Delete (gr_cmd);             
775        }
776        else if ((APDU_Rsp_SW1 (tpdu_rsp) & 0xF0) == 0x60)
777        {
778            /* Map response TPDU onto APDU without change */
779            (*rsp) = tpdu_rsp;
780        }
781        else
782        {
783            /* Delete response TPDU */
784            APDU_Rsp_Delete (tpdu_rsp);
785           
786            /* Prepare extended Get Response APDU command */
787            buffer[0] = APDU_Cmd_Cla (cmd);
788            buffer[1] = 0xC0;
789            buffer[2] = 0x00;
790            buffer[3] = 0x00;
791            buffer[4] = 0x00;     /* B1 = 0x00 */
792            buffer[5] = (BYTE) (APDU_Cmd_Le (cmd) >> 8);  /* B2 = BL-1 */
793            buffer[6] = (BYTE) (APDU_Cmd_Le (cmd) & 0x00FF);      /* B3 = BL */
794           
795            gr_cmd = APDU_Cmd_New (buffer, 7);
796           
797            /* Issue Case 3E get response command */
798            ret = Protocol_T0_Case3E (t0, gr_cmd, rsp);
799           
800            /* Delete Get Response command APDU */
801            APDU_Cmd_Delete (gr_cmd);
802        }
803    }
804    return ret;
805}
806
807
808static int Protocol_T0_ExchangeTPDU (Protocol_T0 * t0, APDU_Cmd * cmd, APDU_Rsp ** rsp)
809{
810    BYTE buffer[PROTOCOL_T0_MAX_SHORT_RESPONSE];
811    BYTE *data;
812    long Lc, Le, sent, recv;
813    int ret = PROTOCOL_T0_OK, nulls, cmd_case;
814   
815    /* Parse APDU */
816    Lc = APDU_Cmd_Lc (cmd);
817    Le = APDU_Cmd_Le (cmd);
818    data = APDU_Cmd_Data (cmd);
819    cmd_case = APDU_Cmd_Case (cmd);
820   
821    /* Check case of command */
822    if ((cmd_case != APDU_CASE_2S) && (cmd_case != APDU_CASE_3S))
823        return PROTOCOL_T0_ERROR;
824   
825    /* Initialise transmission */
826    if (ICC_Async_BeginTransmission (t0->icc) != ICC_ASYNC_OK)
827    {
828        (*rsp) = NULL;
829        return PROTOCOL_T0_ICC_ERROR;
830    }
831   
832    /* Send header bytes */
833    if (ICC_Async_Transmit (t0->icc, 5, APDU_Cmd_Header (cmd)) != ICC_ASYNC_OK)
834    {
835        ICC_Async_EndTransmission (t0->icc);
836       
837        (*rsp) = NULL;
838        return PROTOCOL_T0_ICC_ERROR;
839    }
840   
841    /* Initialise counters */
842    nulls = 0;
843    sent = 0;
844    recv = 0;
845   
846    /*
847    * Let's be a bit paranoid with buffer sizes within this loop
848    * so it doesn't overflow reception and transmission buffers
849    * if card does not strictly respect the protocol
850    */
851   
852    while (recv < PROTOCOL_T0_MAX_SHORT_RESPONSE)
853    {
854        /* Read one procedure byte */
855        if (ICC_Async_Receive (t0->icc, 1, buffer + recv) != ICC_ASYNC_OK)
856        {
857            ret = PROTOCOL_T0_ICC_ERROR;
858            break;
859        }
860       
861        /* NULL byte received */
862        if (buffer[recv] == 0x60)
863        {
864            nulls++;
865           
866            /* Maximum number of nulls reached */
867            if (nulls >= PROTOCOL_T0_MAX_NULLS)
868            {
869                ret = PROTOCOL_T0_NULL_ERROR;
870                break;
871            }
872           
873            continue;
874        }
875        else if ((buffer[recv] & 0xF0) == 0x60 || (buffer[recv] & 0xF0) == 0x90) /* SW1 byte received */
876        {//printf("sw1\n");
877            recv++;
878           
879            if (recv >= PROTOCOL_T0_MAX_SHORT_RESPONSE)
880                return PROTOCOL_T0_ERROR;
881           
882            /* Read SW2 byte */
883            if (ICC_Async_Receive (t0->icc, 1, buffer + recv) != ICC_ASYNC_OK)
884            {
885                ret = PROTOCOL_T0_ICC_ERROR;
886                break;
887            }
888           
889            recv++;
890           
891            ret = PROTOCOL_T0_OK;
892            break;
893        }
894        else if ((buffer[recv] & 0x0E) == (APDU_Cmd_Ins (cmd) & 0x0E)) /* ACK byte received */
895        {//printf("ack\n");
896            /* Reset null's counter */
897            nulls = 0;
898           
899            /* Case 2 command: send data */
900            if (cmd_case == APDU_CASE_2S)
901            {
902                if (sent >= Lc)
903                    return PROTOCOL_T0_ERROR;
904                               
905                if (ICC_Async_Transmit(t0->icc, MAX (Lc - sent, 0), data + sent) != ICC_ASYNC_OK) /* Send remaining data bytes */
906                {
907                    ret = PROTOCOL_T0_ICC_ERROR;
908                    break;
909                }
910               
911                sent = Lc;
912                continue;
913            }
914            else /* Case 3 command: receive data */
915            {
916                if (recv >= PROTOCOL_T0_MAX_SHORT_RESPONSE)
917                    return PROTOCOL_T0_ERROR;
918               
919                /*
920                * Le <= PROTOCOL_T0_MAX_SHORT_RESPONSE - 2 for short commands
921                */
922               
923                /* Read remaining data bytes */
924                if (ICC_Async_Receive(t0->icc, MAX (Le - recv, 0), buffer + recv) != ICC_ASYNC_OK)
925                {//printf("error %d\n", (int)Le);
926                    ret = PROTOCOL_T0_ICC_ERROR;
927                    break;
928                }
929               
930                recv = Le;
931                continue;
932            }
933        }
934        else if ((buffer[recv] & 0x0E) == ((~APDU_Cmd_Ins (cmd)) & 0x0E)) /* ~ACK byte received */
935        {//printf("~ack\n");
936            /* Reset null's counter */
937            nulls = 0;
938           
939            /* Case 2 command: send data */
940            if (cmd_case == APDU_CASE_2S)
941            {
942                if (sent >= Lc)
943                    return PROTOCOL_T0_ERROR;
944                               
945                /* Send next data byte */
946                if (ICC_Async_Transmit (t0->icc, 1, data + sent) !=ICC_ASYNC_OK)
947                {
948                    ret = PROTOCOL_T0_ICC_ERROR;
949                    break;
950                }
951               
952                sent++;
953                continue;
954            }
955            else /* Case 3 command: receive data */
956            {
957                if (recv >= PROTOCOL_T0_MAX_SHORT_RESPONSE)
958                    return PROTOCOL_T0_ERROR;
959               
960                /* Read next data byte */
961                if (ICC_Async_Receive (t0->icc, 1, buffer + recv) != ICC_ASYNC_OK)
962                {
963                    ret = PROTOCOL_T0_ICC_ERROR;
964                    break;
965                }
966               
967                recv++;
968                continue;
969            }
970        }
971        else /* Anything else received */
972        {//printf("hs\n");
973            ret = PROTOCOL_T0_ERROR;
974            break;
975        }
976    }
977       
978    if (ret == PROTOCOL_T0_OK)
979        (*rsp) = APDU_Rsp_New (buffer, recv);
980    else
981        (*rsp) = NULL;
982   
983    /* End of transmission */
984    if (ICC_Async_EndTransmission (t0->icc) != ICC_ASYNC_OK)
985        return PROTOCOL_T0_ICC_ERROR;
986   
987    return (ret);
988}
989
990static int Protocol_T14_ExchangeTPDU (Protocol_T14 * t14, APDU_Cmd * cmd, APDU_Rsp ** rsp)
991{
992    BYTE buffer[PROTOCOL_T14_MAX_SHORT_RESPONSE];
993    BYTE *cmd_raw;
994    long sent, recv, cmd_len;
995    int ret = PROTOCOL_T14_OK, nulls, cmd_case;
996    BYTE ixor = 0x3E;
997    BYTE ixor1 = 0x3F;
998    BYTE b1 = 0x01;
999    int i;
1000   
1001    /* Parse APDU */
1002    cmd_len = APDU_Cmd_Lc (cmd) + 5;
1003    cmd_raw = APDU_Cmd_Raw (cmd);
1004    cmd_case = APDU_Cmd_Case (cmd);
1005    for(i=0; i<cmd_len; i++)
1006        ixor^=cmd_raw[i];
1007
1008    /* Check case of command */
1009    if ((cmd_case != APDU_CASE_2S) && (cmd_case != APDU_CASE_3S))
1010        return PROTOCOL_T14_ERROR;
1011   
1012    /* Initialise transmission */
1013    if (ICC_Async_BeginTransmission (t14->icc) != ICC_ASYNC_OK)
1014    {
1015        (*rsp) = NULL;
1016        return PROTOCOL_T14_ICC_ERROR;
1017    }
1018   
1019    if(t14->icc->ifd->io->com!=RTYP_SCI)
1020    {
1021        /* Send 0x01 byte */
1022        if (ICC_Async_Transmit (t14->icc, 1, &b1) != ICC_ASYNC_OK)
1023        {
1024            ICC_Async_EndTransmission (t14->icc);
1025           
1026            (*rsp) = NULL;
1027            return PROTOCOL_T14_ICC_ERROR;
1028        }
1029       
1030        /* Send apdu */
1031        if (ICC_Async_Transmit (t14->icc, cmd_len, cmd_raw) != ICC_ASYNC_OK)
1032        {
1033            ICC_Async_EndTransmission (t14->icc);
1034           
1035            (*rsp) = NULL;
1036            return PROTOCOL_T14_ICC_ERROR;
1037        }
1038       
1039        /* Send xor byte */
1040        if (ICC_Async_Transmit (t14->icc, 1, &ixor) != ICC_ASYNC_OK)
1041        {
1042            ICC_Async_EndTransmission (t14->icc);
1043           
1044            (*rsp) = NULL;
1045            return PROTOCOL_T14_ICC_ERROR;
1046        }
1047    }
1048    else
1049    {
1050        buffer[0] = 0x01;
1051        memcpy(buffer+1, cmd_raw, cmd_len);
1052        buffer[cmd_len+1] = ixor;
1053       
1054        /* Send apdu */
1055        if (ICC_Async_Transmit (t14->icc, cmd_len+2, buffer) != ICC_ASYNC_OK)
1056        {
1057            ICC_Async_EndTransmission (t14->icc);
1058           
1059            (*rsp) = NULL;
1060            return PROTOCOL_T14_ICC_ERROR;
1061        }
1062    }
1063   
1064    /* Initialise counters */
1065    nulls = 0;
1066    sent = 0;
1067    recv = 0;
1068   
1069   
1070   
1071    /*
1072    * Let's be a bit paranoid with buffer sizes within this loop
1073    * so it doesn't overflow reception and transmission buffers
1074    * if card does not strictly respect the protocol
1075    */
1076   
1077    while (recv < PROTOCOL_T14_MAX_SHORT_RESPONSE)
1078    {
1079        if(cmd_raw[0] == 0x02 && cmd_raw[1] == 0x09)
1080        {
1081#ifdef HAVE_NANOSLEEP
1082            struct timespec req_ts;
1083       
1084//          req_ts.tv_sec = 1;
1085//          req_ts.tv_nsec = 500000000;
1086            req_ts.tv_sec = 2;
1087            req_ts.tv_nsec = 500000000;
1088            nanosleep (&req_ts, NULL);
1089#else
1090            usleep (999999L);
1091#endif
1092        }
1093        /* Read one procedure byte */
1094        if (ICC_Async_Receive (t14->icc, 8, buffer) != ICC_ASYNC_OK)
1095        {
1096            ret = PROTOCOL_T14_ICC_ERROR;
1097            break;
1098        }
1099        else
1100        {
1101            recv = (long)buffer[7];
1102           
1103            if(recv)
1104            {
1105                if (ICC_Async_Receive (t14->icc, recv, buffer + 8) != ICC_ASYNC_OK)
1106                {
1107                    ret = PROTOCOL_T14_ICC_ERROR;
1108                    break;
1109                }
1110            }
1111           
1112            if (ICC_Async_Receive (t14->icc, 1, &ixor) != ICC_ASYNC_OK)
1113            {
1114                ret = PROTOCOL_T14_ICC_ERROR;
1115                break;
1116            }
1117
1118            for(i=0; i<8+recv; i++)     
1119                ixor1^=buffer[i];
1120               
1121            if(ixor1 != ixor)
1122            {
1123                ret = PROTOCOL_T14_ERROR;
1124                break;
1125            }
1126           
1127           
1128           
1129               
1130            ret = PROTOCOL_T14_OK;
1131            break;
1132        }
1133    }
1134       
1135    if (ret == PROTOCOL_T14_OK)
1136    {
1137        memcpy(buffer + 8 + recv, buffer + 2, 2);
1138        (*rsp) = APDU_Rsp_New (buffer + 8, recv + 2);
1139    }
1140    else
1141    {
1142        (*rsp) = NULL;
1143    }
1144   
1145    /* End of transmission */
1146    if (ICC_Async_EndTransmission (t14->icc) != ICC_ASYNC_OK)
1147        return PROTOCOL_T14_ICC_ERROR;
1148   
1149    return (ret);
1150}
1151
1152static void Protocol_T0_Clear (Protocol_T0 * t0)
1153{
1154    t0->icc = NULL;
1155    t0->wwt = 0;
1156}
1157
1158static void Protocol_T14_Clear (Protocol_T14 * t14)
1159{
1160    t14->icc = NULL;
1161    t14->wwt = 0;
1162}
Note: See TracBrowser for help on using the repository browser.