source: branches/monitor-improvement/csctapi/protocol_t0.c@ 1228

Last change on this file since 1228 was 1228, checked in by alno, 13 years ago

WebIf:

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