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.