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