source: trunk/csctapi/protocol_t0.c@ 1279

Last change on this file since 1279 was 1279, checked in by dingo35, 11 years ago

Remove ICC_Async dynamic data structure, cleanup some parameters in t0 and t1

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