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 */
t1_set_defaults(t1_state_t * t1)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
t1_set_checksum(t1_state_t * t1,int csum)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 */
t1_init(t1_state_t * t1,int lun)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 */
t1_release(t1_state_t * t1)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 */
t1_set_param(t1_state_t * t1,int type,long value)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 */
t1_transceive(t1_state_t * t1,unsigned int dad,const void * snd_buf,size_t snd_len,void * rcv_buf,size_t rcv_len)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
t1_block_type(unsigned char pcb)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
t1_seq(unsigned char pcb)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
t1_build(t1_state_t * t1,unsigned char * block,unsigned char dad,unsigned char pcb,ct_buf_t * bp,size_t * lenp)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
t1_rebuild(t1_state_t * t1,unsigned char * block)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 */
t1_compute_checksum(t1_state_t * t1,unsigned char * data,size_t len)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
t1_verify_checksum(t1_state_t * t1,unsigned char * rbuf,size_t len)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 */
t1_xcv(t1_state_t * t1,unsigned char * block,size_t slen,size_t rmax)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
t1_negotiate_ifsd(t1_state_t * t1,unsigned int dad,int ifsd)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 }
801