source: trunk/csctapi/protocol_t0.c@ 1278

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

Cleanup ICC_Async: atr, baudrate, timings, convention

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