Initial commit
[platform/upstream/ccid.git] / src / openct / proto-t1.c
1 /*
2  * Implementation of T=1
3  *
4  * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
5  *
6  * improvements by:
7  * Copyright (C) 2004 Ludovic Rousseau <ludovic.rousseau@free.fr>
8  */
9
10 #include <config.h>
11
12 #include <pcsclite.h>
13 #include <ifdhandler.h>
14 #include "commands.h"
15 #include "buffer.h"
16 #include "debug.h"
17 #include "proto-t1.h"
18 #include "checksum.h"
19
20 #include "ccid.h"
21
22 #ifdef HAVE_STRING_H
23 #include <string.h>
24 #endif
25
26 /* I block */
27 #define T1_I_SEQ_SHIFT          6
28
29 /* R block */
30 #define T1_IS_ERROR(pcb)        ((pcb) & 0x0F)
31 #define T1_EDC_ERROR            0x01
32 #define T1_OTHER_ERROR          0x02
33 #define T1_R_SEQ_SHIFT          4
34
35 /* S block stuff */
36 #define T1_S_IS_RESPONSE(pcb)   ((pcb) & T1_S_RESPONSE)
37 #define T1_S_TYPE(pcb)          ((pcb) & 0x0F)
38 #define T1_S_RESPONSE           0x20
39 #define T1_S_RESYNC             0x00
40 #define T1_S_IFS                0x01
41 #define T1_S_ABORT              0x02
42 #define T1_S_WTX                0x03
43
44 #define swap_nibbles(x) ( (x >> 4) | ((x & 0xF) << 4) )
45
46 #ifndef TRUE
47 #define TRUE 1
48 #define FALSE 0
49 #endif
50
51 #define NAD 0
52 #define PCB 1
53 #define LEN 2
54 #define DATA 3
55
56 /* internal state, do not mess with it. */
57 /* should be != DEAD after reset/init */
58 enum {
59         SENDING, RECEIVING, RESYNCH, DEAD
60 };
61
62 static void t1_set_checksum(t1_state_t *, int);
63 static unsigned int t1_block_type(unsigned char);
64 static unsigned int t1_seq(unsigned char);
65 static unsigned int t1_rebuild(t1_state_t *t1, unsigned char *block);
66 static unsigned int t1_compute_checksum(t1_state_t *, unsigned char *, size_t);
67 static int t1_verify_checksum(t1_state_t *, unsigned char *, size_t);
68 static int t1_xcv(t1_state_t *, unsigned char *, size_t, size_t);
69
70 /*
71  * Set default T=1 protocol parameters
72  */
73 static void t1_set_defaults(t1_state_t * t1)
74 {
75         t1->retries = 3;
76         /* This timeout is rather insane, but we need this right now
77          * to support cryptoflex keygen */
78         t1->ifsc = 32;
79         t1->ifsd = 32;
80         t1->nr = 0;
81         t1->ns = 0;
82         t1->wtx = 0;
83 }
84
85 static void t1_set_checksum(t1_state_t * t1, int csum)
86 {
87         switch (csum) {
88         case IFD_PROTOCOL_T1_CHECKSUM_LRC:
89                 t1->rc_bytes = 1;
90                 t1->checksum = csum_lrc_compute;
91                 break;
92         case IFD_PROTOCOL_T1_CHECKSUM_CRC:
93                 t1->rc_bytes = 2;
94                 t1->checksum = csum_crc_compute;
95                 break;
96         }
97 }
98
99 /*
100  * Attach t1 protocol
101  */
102 int t1_init(t1_state_t * t1, int lun)
103 {
104         t1_set_defaults(t1);
105         t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
106         t1_set_param(t1, IFD_PROTOCOL_T1_STATE, SENDING);
107         t1_set_param(t1, IFD_PROTOCOL_T1_MORE, FALSE);
108
109         t1->lun = lun;
110
111         return 0;
112 }
113
114 /*
115  * Detach t1 protocol
116  */
117 void t1_release(/*@unused@*/ t1_state_t * t1)
118 {
119         (void)t1;
120         /* NOP */
121 }
122
123 /*
124  * Get/set parmaters for T1 protocol
125  */
126 int t1_set_param(t1_state_t * t1, int type, long value)
127 {
128         switch (type) {
129         case IFD_PROTOCOL_T1_CHECKSUM_LRC:
130         case IFD_PROTOCOL_T1_CHECKSUM_CRC:
131                 t1_set_checksum(t1, type);
132                 break;
133         case IFD_PROTOCOL_T1_IFSC:
134                 t1->ifsc = value;
135                 break;
136         case IFD_PROTOCOL_T1_IFSD:
137                 t1->ifsd = value;
138                 break;
139         case IFD_PROTOCOL_T1_STATE:
140                 t1->state = value;
141                 break;
142         case IFD_PROTOCOL_T1_MORE:
143                 t1->more = value;
144                 break;
145         default:
146                 DEBUG_INFO2("Unsupported parameter %d", type);
147                 return -1;
148         }
149
150         return 0;
151 }
152
153 /*
154  * Send an APDU through T=1
155  */
156 int t1_transceive(t1_state_t * t1, unsigned int dad,
157                 const void *snd_buf, size_t snd_len,
158                 void *rcv_buf, size_t rcv_len)
159 {
160         ct_buf_t sbuf, rbuf, tbuf;
161         unsigned char sdata[T1_BUFFER_SIZE], sblk[5];
162         unsigned int slen, retries, resyncs;
163         size_t last_send = 0;
164
165         if (snd_len == 0)
166                 return -1;
167
168         /* we can't talk to a dead card / reader. Reset it! */
169         if (t1->state == DEAD)
170         {
171                 DEBUG_CRITICAL("T=1 state machine is DEAD. Reset the card first.");
172                 return -1;
173         }
174
175         t1->state = SENDING;
176         retries = t1->retries;
177         resyncs = 3;
178
179         /* Initialize send/recv buffer */
180         ct_buf_set(&sbuf, (void *)snd_buf, snd_len);
181         ct_buf_init(&rbuf, rcv_buf, rcv_len);
182
183         /* Send the first block */
184         slen = t1_build(t1, sdata, dad, T1_I_BLOCK, &sbuf, &last_send);
185
186         while (1) {
187                 unsigned char pcb;
188                 int n;
189
190                 retries--;
191
192                 n = t1_xcv(t1, sdata, slen, sizeof(sdata));
193                 if (-2 == n)
194                 {
195                         DEBUG_COMM("Parity error");
196                         /* ISO 7816-3 Rule 7.4.2 */
197                         if (retries <= 0)
198                                 goto resync;
199
200                         /* ISO 7816-3 Rule 7.2 */
201                         if (T1_R_BLOCK == t1_block_type(t1->previous_block[PCB]))
202                         {
203                                 DEBUG_COMM("Rule 7.2");
204                                 slen = t1_rebuild(t1, sdata);
205                                 continue;
206                         }
207
208                         slen = t1_build(t1, sdata,
209                                         dad, T1_R_BLOCK | T1_EDC_ERROR,
210                                         NULL, NULL);
211                         continue;
212                 }
213
214                 if (n < 0) {
215                         DEBUG_CRITICAL("fatal: transmit/receive failed");
216                         t1->state = DEAD;
217                         goto error;
218                 }
219
220                 if ((sdata[NAD] != swap_nibbles(dad)) /* wrong NAD */
221                         || (sdata[LEN] == 0xFF))        /* length == 0xFF (illegal) */
222                 {
223                         DEBUG_COMM("R-BLOCK required");
224                         /* ISO 7816-3 Rule 7.4.2 */
225                         if (retries <= 0)
226                                 goto resync;
227
228                         /* ISO 7816-3 Rule 7.2 */
229                         if (T1_R_BLOCK == t1_block_type(t1->previous_block[PCB]))
230                         {
231                                 DEBUG_COMM("Rule 7.2");
232                                 slen = t1_rebuild(t1, sdata);
233                                 continue;
234                         }
235
236                         slen = t1_build(t1, sdata,
237                                 dad, T1_R_BLOCK | T1_OTHER_ERROR,
238                                 NULL, NULL);
239                         continue;
240                 }
241
242                 if (!t1_verify_checksum(t1, sdata, n)) {
243                         DEBUG_COMM("checksum failed");
244                         /* ISO 7816-3 Rule 7.4.2 */
245                         if (retries <= 0)
246                                 goto resync;
247
248                         /* ISO 7816-3 Rule 7.2 */
249                         if (T1_R_BLOCK == t1_block_type(t1->previous_block[PCB]))
250                         {
251                                 DEBUG_COMM("Rule 7.2");
252                                 slen = t1_rebuild(t1, sdata);
253                                 continue;
254                         }
255
256                         slen = t1_build(t1, sdata,
257                                 dad, T1_R_BLOCK | T1_EDC_ERROR,
258                                 NULL, NULL);
259                         continue;
260                 }
261
262                 pcb = sdata[PCB];
263                 switch (t1_block_type(pcb)) {
264                 case T1_R_BLOCK:
265                         if ((sdata[LEN] != 0x00)        /* length != 0x00 (illegal) */
266                                 || (pcb & 0x20)                 /* b6 of pcb is set */
267                            )
268                         {
269                                 DEBUG_COMM("R-Block required");
270                                 /* ISO 7816-3 Rule 7.4.2 */
271                                 if (retries <= 0)
272                                         goto resync;
273
274                                 /* ISO 7816-3 Rule 7.2 */
275                                 if (T1_R_BLOCK == t1_block_type(t1->previous_block[1]))
276                                 {
277                                         DEBUG_COMM("Rule 7.2");
278                                         slen = t1_rebuild(t1, sdata);
279                                         continue;
280                                 }
281
282                                 slen = t1_build(t1, sdata,
283                                                 dad, T1_R_BLOCK | T1_OTHER_ERROR,
284                                                 NULL, NULL);
285                                 continue;
286                         }
287
288                         if (((t1_seq(pcb) != t1->ns)    /* wrong sequence number & no bit more */
289                                         && ! t1->more)
290                            )
291                         {
292                                 DEBUG_COMM4("received: %d, expected: %d, more: %d",
293                                         t1_seq(pcb), t1->ns, t1->more);
294
295                                 /* ISO 7816-3 Rule 7.4.2 */
296                                 if (retries <= 0)
297                                         goto resync;
298
299                                 /* ISO 7816-3 Rule 7.2 */
300                                 if (T1_R_BLOCK == t1_block_type(t1->previous_block[PCB]))
301                                 {
302                                         DEBUG_COMM("Rule 7.2");
303                                         slen = t1_rebuild(t1, sdata);
304                                         continue;
305                                 }
306
307                                 DEBUG_COMM("R-Block required");
308                                 slen = t1_build(t1, sdata,
309                                                 dad, T1_R_BLOCK | T1_OTHER_ERROR,
310                                                 NULL, NULL);
311                                 continue;
312                         }
313
314                         if (t1->state == RECEIVING) {
315                                 /* ISO 7816-3 Rule 7.2 */
316                                 if (T1_R_BLOCK == t1_block_type(t1->previous_block[1]))
317                                 {
318                                         /* ISO 7816-3 Rule 7.4.2 */
319                                         if (retries <= 0)
320                                                 goto resync;
321
322                                         DEBUG_COMM("Rule 7.2");
323                                         slen = t1_rebuild(t1, sdata);
324                                         continue;
325                                 }
326
327                                 DEBUG_COMM("");
328                                 slen = t1_build(t1, sdata,
329                                                 dad, T1_R_BLOCK,
330                                                 NULL, NULL);
331                                 break;
332                         }
333
334                         /* If the card terminal requests the next
335                          * sequence number, it received the previous
336                          * block successfully */
337                         if (t1_seq(pcb) != t1->ns) {
338                                 ct_buf_get(&sbuf, NULL, last_send);
339                                 last_send = 0;
340                                 t1->ns ^= 1;
341                         }
342
343                         /* If there's no data available, the ICC
344                          * shouldn't be asking for more */
345                         if (ct_buf_avail(&sbuf) == 0)
346                                 goto resync;
347
348                         slen = t1_build(t1, sdata, dad, T1_I_BLOCK,
349                                         &sbuf, &last_send);
350                         break;
351
352                 case T1_I_BLOCK:
353                         /* The first I-block sent by the ICC indicates
354                          * the last block we sent was received successfully. */
355                         if (t1->state == SENDING) {
356                                 DEBUG_COMM("");
357                                 ct_buf_get(&sbuf, NULL, last_send);
358                                 last_send = 0;
359                                 t1->ns ^= 1;
360                         }
361
362                         t1->state = RECEIVING;
363
364                         /* If the block sent by the card doesn't match
365                          * what we expected it to send, reply with
366                          * an R block */
367                         if (t1_seq(pcb) != t1->nr) {
368                                 DEBUG_COMM("wrong nr");
369
370                                 /* ISO 7816-3 Rule 7.4.2 */
371                                 if (retries <= 0)
372                                         goto resync;
373
374                                 slen = t1_build(t1, sdata, dad,
375                                                 T1_R_BLOCK | T1_OTHER_ERROR,
376                                                 NULL, NULL);
377                                 continue;
378                         }
379
380                         t1->nr ^= 1;
381
382                         if (ct_buf_put(&rbuf, sdata + 3, sdata[LEN]) < 0)
383                         {
384                                 DEBUG_CRITICAL2("buffer overrun by %d bytes", sdata[LEN] - (rbuf.size - rbuf.tail));
385                                 goto error;
386                         }
387
388                         if ((pcb & T1_MORE_BLOCKS) == 0)
389                                 goto done;
390
391                         slen = t1_build(t1, sdata, dad, T1_R_BLOCK, NULL, NULL);
392                         break;
393
394                 case T1_S_BLOCK:
395                         if (T1_S_IS_RESPONSE(pcb) && t1->state == RESYNCH) {
396                                 /* ISO 7816-3 Rule 6.2 */
397                                 DEBUG_COMM("S-Block answer received");
398                                 /* ISO 7816-3 Rule 6.3 */
399                                 t1->state = SENDING;
400                                 last_send = 0;
401                                 resyncs = 3;
402                                 retries = t1->retries;
403                                 ct_buf_init(&rbuf, rcv_buf, rcv_len);
404                                 slen = t1_build(t1, sdata, dad, T1_I_BLOCK,
405                                                 &sbuf, &last_send);
406                                 continue;
407                         }
408
409                         if (T1_S_IS_RESPONSE(pcb))
410                         {
411                                 /* ISO 7816-3 Rule 7.4.2 */
412                                 if (retries <= 0)
413                                         goto resync;
414
415                                 /* ISO 7816-3 Rule 7.2 */
416                                 if (T1_R_BLOCK == t1_block_type(t1->previous_block[PCB]))
417                                 {
418                                         DEBUG_COMM("Rule 7.2");
419                                         slen = t1_rebuild(t1, sdata);
420                                         continue;
421                                 }
422
423                                 DEBUG_CRITICAL("wrong response S-BLOCK received");
424                                 slen = t1_build(t1, sdata,
425                                                 dad, T1_R_BLOCK | T1_OTHER_ERROR,
426                                                 NULL, NULL);
427                                 continue;
428                         }
429
430                         ct_buf_init(&tbuf, sblk, sizeof(sblk));
431
432                         DEBUG_COMM("S-Block request received");
433                         switch (T1_S_TYPE(pcb)) {
434                         case T1_S_RESYNC:
435                                 if (sdata[LEN] != 0)
436                                 {
437                                         DEBUG_COMM2("Wrong length: %d", sdata[LEN]);
438                                         slen = t1_build(t1, sdata, dad,
439                                                 T1_R_BLOCK | T1_OTHER_ERROR,
440                                                 NULL, NULL);
441                                         continue;
442                                 }
443
444                                 DEBUG_COMM("Resync requested");
445                                 /* the card is not allowed to send a resync. */
446                                 goto resync;
447
448                         case T1_S_ABORT:
449                                 if (sdata[LEN] != 0)
450                                 {
451                                         DEBUG_COMM2("Wrong length: %d", sdata[LEN]);
452                                         slen = t1_build(t1, sdata, dad,
453                                                 T1_R_BLOCK | T1_OTHER_ERROR,
454                                                 NULL, NULL);
455                                         continue;
456                                 }
457
458                                 /* ISO 7816-3 Rule 9 */
459                                 DEBUG_CRITICAL("abort requested");
460                                 break;
461
462                         case T1_S_IFS:
463                                 if (sdata[LEN] != 1)
464                                 {
465                                         DEBUG_COMM2("Wrong length: %d", sdata[LEN]);
466                                         slen = t1_build(t1, sdata, dad,
467                                                 T1_R_BLOCK | T1_OTHER_ERROR,
468                                                 NULL, NULL);
469                                         continue;
470                                 }
471
472                                 DEBUG_CRITICAL2("CT sent S-block with ifs=%u", sdata[DATA]);
473                                 if (sdata[DATA] == 0)
474                                         goto resync;
475                                 t1->ifsc = sdata[DATA];
476                                 ct_buf_putc(&tbuf, sdata[DATA]);
477                                 break;
478
479                         case T1_S_WTX:
480                                 if (sdata[LEN] != 1)
481                                 {
482                                         DEBUG_COMM2("Wrong length: %d", sdata[LEN]);
483                                         slen = t1_build(t1, sdata, dad,
484                                                 T1_R_BLOCK | T1_OTHER_ERROR,
485                                                 NULL, NULL);
486                                         continue;
487                                 }
488
489                                 DEBUG_COMM2("CT sent S-block with wtx=%u", sdata[DATA]);
490                                 t1->wtx = sdata[DATA];
491                                 ct_buf_putc(&tbuf, sdata[DATA]);
492                                 break;
493
494                         default:
495                                 DEBUG_CRITICAL2("T=1: Unknown S block type 0x%02x", T1_S_TYPE(pcb));
496                                 goto resync;
497                         }
498
499                         slen = t1_build(t1, sdata, dad,
500                                 T1_S_BLOCK | T1_S_RESPONSE | T1_S_TYPE(pcb),
501                                 &tbuf, NULL);
502                 }
503
504                 /* Everything went just splendid */
505                 retries = t1->retries;
506                 continue;
507
508 resync:
509                 /* the number or resyncs is limited, too */
510                 /* ISO 7816-3 Rule 6.4 */
511                 if (resyncs == 0)
512                         goto error;
513
514                 /* ISO 7816-3 Rule 6 */
515                 resyncs--;
516                 t1->ns = 0;
517                 t1->nr = 0;
518                 slen = t1_build(t1, sdata, dad, T1_S_BLOCK | T1_S_RESYNC, NULL,
519                                 NULL);
520                 t1->state = RESYNCH;
521                 t1->more = FALSE;
522                 retries = 1;
523                 continue;
524         }
525
526 done:
527         return ct_buf_avail(&rbuf);
528
529 error:
530         t1->state = DEAD;
531         return -1;
532 }
533
534 static unsigned t1_block_type(unsigned char pcb)
535 {
536         switch (pcb & 0xC0) {
537         case T1_R_BLOCK:
538                 return T1_R_BLOCK;
539         case T1_S_BLOCK:
540                 return T1_S_BLOCK;
541         default:
542                 return T1_I_BLOCK;
543         }
544 }
545
546 static unsigned int t1_seq(unsigned char pcb)
547 {
548         switch (pcb & 0xC0) {
549         case T1_R_BLOCK:
550                 return (pcb >> T1_R_SEQ_SHIFT) & 1;
551         case T1_S_BLOCK:
552                 return 0;
553         default:
554                 return (pcb >> T1_I_SEQ_SHIFT) & 1;
555         }
556 }
557
558 unsigned int t1_build(t1_state_t * t1, unsigned char *block,
559         unsigned char dad, unsigned char pcb,
560         ct_buf_t *bp, size_t *lenp)
561 {
562         unsigned int len;
563         char more = FALSE;
564
565         len = bp ? ct_buf_avail(bp) : 0;
566         if (len > t1->ifsc) {
567                 pcb |= T1_MORE_BLOCKS;
568                 len = t1->ifsc;
569                 more = TRUE;
570         }
571
572         /* Add the sequence number */
573         switch (t1_block_type(pcb)) {
574         case T1_R_BLOCK:
575                 pcb |= t1->nr << T1_R_SEQ_SHIFT;
576                 break;
577         case T1_I_BLOCK:
578                 pcb |= t1->ns << T1_I_SEQ_SHIFT;
579                 t1->more = more;
580                 DEBUG_COMM2("more bit: %d", more);
581                 break;
582         }
583
584         block[0] = dad;
585         block[1] = pcb;
586         block[2] = len;
587
588         if (len)
589                 memcpy(block + 3, ct_buf_head(bp), len);
590         if (lenp)
591                 *lenp = len;
592
593         len = t1_compute_checksum(t1, block, len + 3);
594
595         /* memorize the last sent block */
596         /* only 4 bytes since we are only interesed in R-blocks */
597         memcpy(t1->previous_block, block, 4);
598
599         return len;
600 }
601
602 static unsigned int
603 t1_rebuild(t1_state_t *t1, unsigned char *block)
604 {
605         unsigned char pcb = t1 -> previous_block[1];
606
607         /* copy the last sent block */
608         if (T1_R_BLOCK == t1_block_type(pcb))
609                 memcpy(block, t1 -> previous_block, 4);
610         else
611         {
612                 DEBUG_CRITICAL2("previous block was not R-Block: %02X", pcb);
613                 return 0;
614         }
615
616         return 4;
617 }
618
619 /*
620  * Build/verify checksum
621  */
622 static unsigned int t1_compute_checksum(t1_state_t * t1,
623         unsigned char *data, size_t len)
624 {
625         return len + t1->checksum(data, len, data + len);
626 }
627
628 static int t1_verify_checksum(t1_state_t * t1, unsigned char *rbuf,
629         size_t len)
630 {
631         unsigned char csum[2];
632         int m, n;
633
634         m = len - t1->rc_bytes;
635         n = t1->rc_bytes;
636
637         if (m < 0)
638                 return 0;
639
640         t1->checksum(rbuf, m, csum);
641         if (!memcmp(rbuf + m, csum, n))
642                 return 1;
643
644         return 0;
645 }
646
647 /*
648  * Send/receive block
649  */
650 static int t1_xcv(t1_state_t * t1, unsigned char *block, size_t slen,
651         size_t rmax)
652 {
653         int n;
654         _ccid_descriptor *ccid_desc ;
655         int oldReadTimeout;
656         unsigned int rmax_int;
657
658         DEBUG_XXD("sending: ", block, slen);
659
660         ccid_desc = get_ccid_descriptor(t1->lun);
661         oldReadTimeout = ccid_desc->readTimeout;
662
663         if (t1->wtx > 1)
664         {
665                 /* set the new temporary timeout at WTX card request */
666                 ccid_desc->readTimeout *=  t1->wtx;
667                 DEBUG_INFO2("New timeout at WTX request: %d sec",
668                         ccid_desc->readTimeout);
669         }
670
671         if (isCharLevel(t1->lun))
672         {
673                 rmax = 3;
674
675                 n = CCID_Transmit(t1 -> lun, slen, block, rmax, t1->wtx);
676                 if (n != IFD_SUCCESS)
677                         return -1;
678
679                 /* the second argument of CCID_Receive() is (unsigned int *)
680                  * so we can't use &rmax since &rmax is a (size_t *) and may not
681                  * be the same on 64-bits architectures for example (iMac G5) */
682                 rmax_int = rmax;
683                 n = CCID_Receive(t1 -> lun, &rmax_int, block, NULL);
684
685                 if (n == IFD_PARITY_ERROR)
686                         return -2;
687                 if (n != IFD_SUCCESS)
688                         return -1;
689
690                 rmax = block[2] + 1;
691
692                 n = CCID_Transmit(t1 -> lun, 0, block, rmax, t1->wtx);
693                 if (n != IFD_SUCCESS)
694                         return -1;
695
696                 rmax_int = rmax;
697                 n = CCID_Receive(t1 -> lun, &rmax_int, &block[3], NULL);
698                 rmax = rmax_int;
699                 if (n == IFD_PARITY_ERROR)
700                         return -2;
701                 if (n != IFD_SUCCESS)
702                         return -1;
703
704                 n = rmax + 3;
705         }
706         else
707         {
708                 n = CCID_Transmit(t1 -> lun, slen, block, 0, t1->wtx);
709                 t1->wtx = 0;    /* reset to default value */
710                 if (n != IFD_SUCCESS)
711                         return -1;
712
713                 /* Get the response en bloc */
714                 rmax_int = rmax;
715                 n = CCID_Receive(t1 -> lun, &rmax_int, block, NULL);
716                 rmax = rmax_int;
717                 if (n == IFD_PARITY_ERROR)
718                         return -2;
719                 if (n != IFD_SUCCESS)
720                         return -1;
721
722                 n = rmax;
723         }
724
725         if (n >= 0)
726         {
727                 int m;
728
729                 m = block[2] + 3 + t1->rc_bytes;
730                 if (m < n)
731                         n = m;
732         }
733
734         if (n >= 0)
735                 DEBUG_XXD("received: ", block, n);
736
737         /* Restore initial timeout */
738         ccid_desc->readTimeout = oldReadTimeout;
739
740         return n;
741 }
742
743 int t1_negotiate_ifsd(t1_state_t * t1, unsigned int dad, int ifsd)
744 {
745         ct_buf_t sbuf;
746         unsigned char sdata[T1_BUFFER_SIZE];
747         unsigned int slen;
748         unsigned int retries;
749         size_t snd_len;
750         int n;
751         unsigned char snd_buf[1];
752
753         retries = t1->retries;
754
755         /* S-block IFSD request */
756         snd_buf[0] = ifsd;
757         snd_len = 1;
758
759         /* Initialize send/recv buffer */
760         ct_buf_set(&sbuf, (void *)snd_buf, snd_len);
761
762         while (TRUE)
763         {
764                 /* Build the block */
765                 slen = t1_build(t1, sdata, 0, T1_S_BLOCK | T1_S_IFS, &sbuf, NULL);
766
767                 /* Send the block */
768                 n = t1_xcv(t1, sdata, slen, sizeof(sdata));
769
770                 retries--;
771                 /* ISO 7816-3 Rule 7.4.2 */
772                 if (retries <= 0)
773                         goto error;
774
775                 if (-1 == n)
776                 {
777                         DEBUG_CRITICAL("fatal: transmit/receive failed");
778                         goto error;
779                 }
780
781                 if ((-2 == n)                                                           /* Parity error */
782                         || (sdata[DATA] != ifsd)                                /* Wrong ifsd received */
783                         || (sdata[NAD] != swap_nibbles(dad))    /* wrong NAD */
784                         || (!t1_verify_checksum(t1, sdata, n))  /* checksum failed */
785                         || (n != 4 + (int)t1->rc_bytes)                         /* wrong frame length */
786                         || (sdata[LEN] != 1)                                    /* wrong data length */
787                         || (sdata[PCB] != (T1_S_BLOCK | T1_S_RESPONSE | T1_S_IFS))) /* wrong PCB */
788                         continue;
789
790                 /* no more error */
791                 goto done;
792         }
793
794 done:
795         return n;
796
797 error:
798         t1->state = DEAD;
799         return -1;
800 }