1 /*****************************************************************************
2  * Copyright ©2017-2019 Gemalto – a Thales Company. All rights Reserved.
3  *
4  * This copy is licensed under the Apache License, Version 2.0 (the "License");
5  * You may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *     http://www.apache.org/licenses/LICENSE-2.0 or https://www.apache.org/licenses/LICENSE-2.0.html
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10  * See the License for the specific language governing permissions and limitations under the License.
11 
12  ****************************************************************************/
13 
14 /**
15  * @file
16  * $Author$
17  * $Revision$
18  * $Date$
19  *
20  * T=1 implementation.
21  *
22  */
23 
24 #include <stddef.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <stdint.h>
33 #include <fcntl.h>
34 #include <log/log.h>
35 
36 #include "iso7816_t1.h"
37 #include "checksum.h"
38 #include "transport.h"
39 
40 #define T1_REQUEST_RESYNC 0x00
41 #define T1_REQUEST_IFS    0x01
42 #define T1_REQUEST_ABORT  0x02
43 #define T1_REQUEST_WTX    0x03
44 #define T1_REQUEST_RESET  0x05 /* Custom RESET for SPI version */
45 
46 #define MAX_RETRIES 3
47 
48 #define MAX_WTX_ROUNDS 100
49 
50 #define WTX_MAX_VALUE 1
51 
52 static void
t1_init_recv_window(struct t1_state * t1,void * buf,size_t n)53 t1_init_recv_window(struct t1_state *t1, void *buf, size_t n)
54 {
55     t1->recv.start = t1->recv.end = buf;
56     t1->recv.size  = n;
57 }
58 
59 static ptrdiff_t
t1_recv_window_free_size(struct t1_state * t1)60 t1_recv_window_free_size(struct t1_state *t1)
61 {
62     return (ptrdiff_t)t1->recv.size - (t1->recv.end - t1->recv.start);
63 }
64 
65 static void
t1_recv_window_append(struct t1_state * t1,const void * buf,int n)66 t1_recv_window_append(struct t1_state *t1, const void *buf, int n)
67 {
68     ptrdiff_t free = t1_recv_window_free_size(t1);
69     ALOGE("gto_esehal SecureElement:t1_recv_window_append free = %d\n", free);
70     if (n > free)
71         n = (int)free;
72     if (n > 0) {
73         memcpy(t1->recv.end, buf, (size_t)n);
74         t1->recv.end += n;
75     }
76 }
77 
78 static ptrdiff_t
t1_recv_window_size(struct t1_state * t1)79 t1_recv_window_size(struct t1_state *t1)
80 {
81     return t1->recv.end - t1->recv.start;
82 }
83 
84 static void
t1_close_recv_window(struct t1_state * t1)85 t1_close_recv_window(struct t1_state *t1)
86 {
87     t1->recv.start = t1->recv.end;
88     t1->recv.size  = 0;
89 }
90 
91 static void
t1_init_send_window(struct t1_state * t1,const void * buf,size_t n)92 t1_init_send_window(struct t1_state *t1, const void *buf, size_t n)
93 {
94     t1->send.start = buf;
95     t1->send.end   = t1->send.start + n;
96 }
97 
98 static ptrdiff_t
t1_send_window_size(struct t1_state * t1)99 t1_send_window_size(struct t1_state *t1)
100 {
101     return t1->send.end - t1->send.start;
102 }
103 
104 static void
t1_close_send_window(struct t1_state * t1)105 t1_close_send_window(struct t1_state *t1)
106 {
107     t1->send.end = t1->send.start;
108 }
109 
110 static int
do_chk(struct t1_state * t1,uint8_t * buf)111 do_chk(struct t1_state *t1, uint8_t *buf)
112 {
113     int n = 3 + buf[2];
114 
115     switch (t1->chk_algo) {
116         case CHECKSUM_LRC:
117             buf[n] = lrc8(buf, n);
118             n++;
119             break;
120 
121         case CHECKSUM_CRC: {
122             uint16_t crc = crc_ccitt(0xFFFF, buf, n);
123             buf[n++] = (uint8_t)(crc >> 8);
124             buf[n++] = (uint8_t)(crc);
125             break;
126         }
127     }
128     return n;
129 }
130 
131 static int
chk_is_good(struct t1_state * t1,const uint8_t * buf)132 chk_is_good(struct t1_state *t1, const uint8_t *buf)
133 {
134     int n = 3 + buf[2];
135     int match;
136 
137     switch (t1->chk_algo) {
138         case CHECKSUM_LRC:
139             match = (buf[n] == lrc8(buf, n));
140             break;
141 
142         case CHECKSUM_CRC: {
143             uint16_t crc = crc_ccitt(0xFFFF, buf, n);
144             match = (crc == (buf[n + 1] | (buf[n] << 8)));
145             break;
146         }
147 
148         default:
149             match = 0;
150     }
151     return match;
152 }
153 
154 static int
write_iblock(struct t1_state * t1,uint8_t * buf)155 write_iblock(struct t1_state *t1, uint8_t *buf)
156 {
157     ptrdiff_t n = t1_send_window_size(t1);
158     uint8_t   pcb;
159 
160     /* Card asking for more data whereas nothing is left.*/
161     if (n <= 0)
162         return -EBADMSG;
163 
164     if (n > t1->ifsc)
165         n = t1->ifsc, pcb = 0x20;
166     else
167         pcb = 0;
168 
169     if (t1->send.next)
170         pcb |= 0x40;
171 
172     buf[0] = t1->nad;
173     buf[1] = pcb;
174     buf[2] = (uint8_t)n;
175     memcpy(buf + 3, t1->send.start, (size_t)n);
176     return do_chk(t1, buf);
177 }
178 
179 static int
write_rblock(struct t1_state * t1,int n,uint8_t * buf)180 write_rblock(struct t1_state *t1, int n, uint8_t *buf)
181 {
182     buf[0] = t1->nad;
183     buf[1] = 0x80 | (n & 3);
184     if (t1->recv.next)
185         buf[1] |= 0x10;
186     buf[2] = 0;
187     return do_chk(t1, buf);
188 }
189 
190 static int
write_request(struct t1_state * t1,int request,uint8_t * buf)191 write_request(struct t1_state *t1, int request, uint8_t *buf)
192 {
193     buf[0] = t1->nad;
194     buf[1] = 0xC0 | request;
195 
196     request &= 0x1F;
197     if (T1_REQUEST_IFS == request) {
198         /* On response, resend card IFS, else this is request for device IFS */
199         buf[2] = 1;
200         if (buf[1] & 0x20)
201             buf[3] = t1->ifsc;
202         else
203             buf[3] = t1->ifsd;
204     } else if (T1_REQUEST_WTX == request) {
205         buf[2] = 1;
206         buf[3] = t1->wtx;
207     } else
208         buf[2] = 0;
209 
210     return do_chk(t1, buf);
211 }
212 
213 static void
ack_iblock(struct t1_state * t1)214 ack_iblock(struct t1_state *t1)
215 {
216     ptrdiff_t n = t1_send_window_size(t1);
217 
218     if (n > t1->ifsc)
219         n = t1->ifsc;
220     t1->send.start += n;
221 
222     /* Next packet sequence number */
223     t1->send.next ^= 1;
224 }
225 
226 /* 0 if not more block, 1 otherwize */
227 static int
parse_iblock(struct t1_state * t1,uint8_t * buf)228 parse_iblock(struct t1_state *t1, uint8_t *buf)
229 {
230     uint8_t pcb  = buf[1];
231     uint8_t next = !!(pcb & 0x40);
232 
233     if (t1->recv.next == next) {
234         t1->recv.next ^= 1;
235         t1_recv_window_append(t1, buf + 3, buf[2]);
236         t1->recv_size += buf[2];
237     }
238 
239     /* 1 if more to come */
240     return !!(pcb & 0x20);
241 }
242 
243 static int
parse_rblock(struct t1_state * t1,uint8_t * buf)244 parse_rblock(struct t1_state *t1, uint8_t *buf)
245 {
246     int     r    = 0;
247     uint8_t pcb  = buf[1];
248     uint8_t next = !!(pcb & 0x10);
249 
250     switch (pcb & 0x2F) {
251         case 0:
252             if ((t1->send.next ^ next) != 0) {
253                 /* Acknowledge previous block */
254                 t1->retries = MAX_RETRIES;
255                 ack_iblock(t1);
256             } else {
257                 t1->retries--;
258                 if (t1->retries <= 0) r = -ETIMEDOUT;
259             }
260             break;
261 
262         case 1:
263             t1->retries--;
264             t1->send.next = next;
265             r = -EREMOTEIO;
266             /* CRC error on previous block, will resend */
267             break;
268 
269         case 2:
270             /* Error */
271             t1->state.halt = 1; r = -EIO;
272             break;
273 
274         case 3:
275             t1->retries--;
276             r = -EREMOTEIO;
277             t1->state.request = 1;
278             t1->request       = T1_REQUEST_RESYNC;
279             break;
280 
281         default:
282             t1->state.halt = 1; r = -EOPNOTSUPP;
283             break;
284     }
285     return r;
286 }
287 
288 static int
parse_request(struct t1_state * t1,uint8_t * buf)289 parse_request(struct t1_state *t1, uint8_t *buf)
290 {
291     int n = 0;
292 
293     uint8_t request = buf[1] & 0x3F;
294 
295     t1->request = request;
296     switch (request) {
297         case T1_REQUEST_RESYNC:
298             n = -EOPNOTSUPP;
299             break;
300 
301         case T1_REQUEST_IFS:
302             if (buf[2] != 1)
303                 n = -EBADMSG;
304             else if ((buf[3] == 0) || (buf[3] == 0xFF))
305                 n = -EBADMSG;
306             else
307                 t1->ifsc = buf[3];
308             break;
309 
310         case T1_REQUEST_ABORT:
311             if (buf[2] == 0) {
312                 t1->state.aborted = 1;
313                 t1_close_send_window(t1);
314                 t1_close_recv_window(t1);
315             } else
316                 n = -EBADMSG;
317             break;
318 
319         case T1_REQUEST_WTX:
320             if (buf[2] > 1) {
321                 n = -EBADMSG;
322                 break;
323             } else if (buf[2] == 1) {
324                 t1->wtx = buf[3];
325                 if (t1->wtx_max_value)
326                     if (t1->wtx > WTX_MAX_VALUE)
327                         t1->wtx = WTX_MAX_VALUE;
328                 if (t1->wtx_max_rounds) {
329                     t1->wtx_rounds--;
330                     if (t1->wtx_rounds <= 0) {
331                         t1->retries = 0;
332                         n = -EBADE;
333                     }
334                 }
335             }
336             break;
337 
338         default:
339             n = -EOPNOTSUPP;
340             break;
341     }
342 
343     /* Prepare response for next loop step */
344     if (n == 0)
345         t1->state.reqresp = 1;
346 
347     return n;
348 }
349 
350 /* Find if ATR is changing IFSC value */
351 static void
parse_atr(struct t1_state * t1)352 parse_atr(struct t1_state *t1)
353 {
354     const uint8_t *atr = t1->atr;
355     size_t         n = t1->atr_length;
356     int            c, y, tck, proto = 0, ifsc = -1;
357 
358     /* Parse T0 byte */
359     tck = y = (n > 0 ? atr[0] : 0);
360 
361     /* Parse interface bytes */
362     for (size_t j = 1; j < n; j++) {
363         c    = atr[j];
364         tck ^= c;
365 
366         if ((y & 0xF0) == 0x80)
367             /* This is TDi byte */
368             y = c, proto |= (1 << (c & 15));
369         else if (y >= 16) {
370             /* First TA for T=1 */
371             if ((ifsc < 0) && ((y & 0x1F) == 0x11))
372                 ifsc = c;
373             /* Clear interface byte flag just seen */
374             y &= y - 16;
375         } else /* No more interface bytes */
376             y = -1;
377     }
378 
379     /* If TA for T=1 seen and ATR checksum is valid */
380     if ((proto & 2) && (tck == 0))
381         t1->ifsc = (uint8_t)ifsc;
382 }
383 
384 /* 1 if expected response, 0 if reemit I-BLOCK, negative value is error */
385 static int
parse_response(struct t1_state * t1,uint8_t * buf)386 parse_response(struct t1_state *t1, uint8_t *buf)
387 {
388     int     r;
389     uint8_t pcb = buf[1];
390 
391     r = 0;
392 
393     /* Not a response ? */
394     if (pcb & 0x20) {
395         pcb &= 0x1F;
396         if (pcb == t1->request) {
397             r = 1;
398             switch (pcb) {
399                 case T1_REQUEST_IFS:
400 				    t1->need_ifsd_sync = 0;
401                     if ((buf[2] != 1) && (buf[3] != t1->ifsd))
402                         r = -EBADMSG;
403                     break;
404 
405                 case T1_REQUEST_RESET:
406                     t1->need_reset = 0;
407                     if (buf[2] <= sizeof(t1->atr)) {
408                         t1->atr_length = buf[2];
409                         if (t1->atr_length)
410                             memcpy(t1->atr, buf + 3, t1->atr_length);
411                         parse_atr(t1);
412                     } else
413                         r = -EBADMSG;
414                     break;
415                 case T1_REQUEST_RESYNC:
416                     t1->need_resync = 0;
417                     t1->send.next = 0;
418                     t1->recv.next = 0;
419                     break;
420                 case T1_REQUEST_ABORT:
421 
422                 default:
423                     /* We never emitted those requests */
424                     r = -EBADMSG;
425                     break;
426             }
427         }
428     }
429     return r;
430 }
431 
432 enum { T1_IBLOCK, T1_RBLOCK, T1_SBLOCK };
433 
434 static int
block_kind(const uint8_t * buf)435 block_kind(const uint8_t *buf)
436 {
437     if ((buf[1] & 0x80) == 0)
438         return T1_IBLOCK;
439     else if ((buf[1] & 0x40) == 0)
440         return T1_RBLOCK;
441     else
442         return T1_SBLOCK;
443 }
444 
445 static int
read_block(struct t1_state * t1)446 read_block(struct t1_state *t1)
447 {
448     int n;
449 
450     n = block_recv(t1, t1->buf, sizeof(t1->buf));
451 
452     if (n < 0)
453         return n;
454     else if (n < 3)
455         return -EBADMSG;
456     else {
457         if (!chk_is_good(t1, t1->buf))
458             return -EREMOTEIO;
459 
460         if (t1->buf[0] != t1->nadc)
461             return -EBADMSG;
462 
463         if (t1->buf[2] == 255)
464             return -EBADMSG;
465     }
466 
467     return n;
468 }
469 
470 static int
t1_loop(struct t1_state * t1)471 t1_loop(struct t1_state *t1)
472 {
473     int len;
474     int n = 0;
475 
476     /* Will happen on first run */
477     if (t1->need_reset) {
478         t1->state.request = 1;
479         t1->request       = T1_REQUEST_RESET;
480     } else if (t1->need_resync) {
481         t1->state.request = 1;
482         t1->request       = T1_REQUEST_RESYNC;
483     }else if(t1->need_ifsd_sync){
484 		t1->state.request = 1;
485         t1->request = T1_REQUEST_IFS;
486         t1->ifsd    = 254;
487 	}
488 
489     while (!t1->state.halt && t1->retries) {
490         if (t1->state.request)
491             n = write_request(t1, t1->request, t1->buf);
492         else if (t1->state.reqresp) {
493             n = write_request(t1, 0x20 | t1->request, t1->buf);
494             /* If response is not seen, card will repost request */
495             t1->state.reqresp = 0;
496         } else if (t1->state.badcrc)
497             /* FIXME "1" -> T1_RBLOCK_CRC_ERROR */
498             n = write_rblock(t1, 1, t1->buf);
499         else if (t1->state.timeout)
500             n = write_rblock(t1, 0, t1->buf);
501         else if (t1_send_window_size(t1))
502             n = write_iblock(t1, t1->buf);
503         else if (t1->state.aborted)
504             n = -EPIPE;
505         else if (t1_recv_window_size(t1) >= 0)
506             /* Acknowledges block received so far */
507             n = write_rblock(t1, 0, t1->buf);
508         else
509             /* Card did not send an I-BLOCK for response */
510             n = -EBADMSG;
511 
512         if (n < 0)
513             break;
514 
515         len = block_send(t1, t1->buf, n);
516         if (len < 0) {
517             /* failure to send is permanent, give up immediately */
518             n = len;
519             break;
520         }
521 
522         n = read_block(t1);
523         if (n < 0) {
524             t1->retries--;
525             switch (n) {
526                 /* Error that trigger recovery */
527                 case -EREMOTEIO:
528                     /* Emit checksum error R-BLOCK */
529                     t1->state.badcrc = 1;
530                     continue;
531 
532                 case -ETIMEDOUT:
533                     /* resend block */
534                     t1->state.timeout = 1;
535                     /* restore checksum failure error */
536                     if (t1->state.badcrc)
537                         n = -EREMOTEIO;
538                     continue;
539 
540                 /* Block read implementation failed */
541                 case -EBADMSG: /* fall through */
542 
543                 /* Other errors are platform specific and not recoverable. */
544                 default:
545                     t1->retries = 0;
546                     continue;
547             }
548             /* Shall never reach this line */
549             break;
550         }
551 
552         if (t1->state.badcrc)
553             if ((t1->buf[1] & 0xEF) == 0x81) {
554                 /* Resent bad checksum R-BLOCK when response is CRC failure. */
555                 t1->retries--;
556                 n = -EREMOTEIO;
557                 continue;
558             }
559 
560         t1->state.badcrc  = 0;
561         t1->state.timeout = 0;
562 
563         if (t1->state.request) {
564             if (block_kind(t1->buf) == T1_SBLOCK) {
565                 n = parse_response(t1, t1->buf);
566                 switch (n) {
567                     case 0:
568                         /* Asked to emit same former I-BLOCK */
569                         break;
570 
571                     case 1:
572                         t1->state.request = 0;
573                         /* Nothing to do ? leave */
574                         if (t1_recv_window_free_size(t1) == 0)
575                             t1->state.halt = 1, n = 0;
576                         t1->retries = MAX_RETRIES;
577 						if(t1->request       == T1_REQUEST_RESET) {
578 							t1->state.request = 1;
579                             t1->request = T1_REQUEST_IFS;
580                             t1->ifsd    = 254;
581 							t1->need_ifsd_sync = 1;
582 						}
583                         continue;
584 
585                     default: /* Negative return is error */
586                         t1->state.halt = 1;
587                         continue;
588                 }
589             }
590             /* Re-emit request until response received */
591             t1->retries--;
592             n = -EBADE;
593         } else {
594             switch (block_kind(t1->buf)) {
595                 case T1_IBLOCK:
596                     t1->retries = MAX_RETRIES;
597                     if (t1_send_window_size(t1))
598                         /* Acknowledges last IBLOCK sent */
599                         ack_iblock(t1);
600                     n = parse_iblock(t1, t1->buf);
601                     if (t1->state.aborted)
602                         continue;
603                     if (t1->recv_size > t1->recv_max) {
604                         /* Too much data received */
605                         n = -EMSGSIZE;
606                         t1->state.halt = 1;
607                         continue;
608                     }
609                     if ((n == 0) && (t1_send_window_size(t1) == 0))
610                         t1->state.halt = 1;
611                     t1->wtx_rounds = t1->wtx_max_rounds;
612                     break;
613 
614                 case T1_RBLOCK:
615                     n = parse_rblock(t1, t1->buf);
616                     t1->wtx_rounds = t1->wtx_max_rounds;
617                     break;
618 
619                 case T1_SBLOCK:
620                     n = parse_request(t1, t1->buf);
621                     if (n == 0)
622                         /* Send request response on next loop. */
623                         t1->state.reqresp = 1;
624                     else if ((n == -EBADMSG) || (n == -EOPNOTSUPP))
625                         t1->state.halt = 1;
626                     break;
627             }
628         }
629     }
630     return n;
631 }
632 
633 static void
t1_clear_states(struct t1_state * t1)634 t1_clear_states(struct t1_state *t1)
635 {
636     t1->state.halt    = 0;
637     t1->state.request = 0;
638     t1->state.reqresp = 0;
639     t1->state.badcrc  = 0;
640     t1->state.timeout = 0;
641     t1->state.aborted = 0;
642 
643     t1->wtx     = 1;
644     t1->retries = MAX_RETRIES;
645     t1->request = 0xFF;
646 
647     t1->wtx_rounds = t1->wtx_max_rounds;
648 
649     t1->send.start = t1->send.end = NULL;
650     t1->recv.start = t1->recv.end = NULL;
651     t1->recv.size  = 0;
652 
653     t1->recv_size = 0;  /* Also count discarded bytes */
654 }
655 
656 static void
t1_init(struct t1_state * t1)657 t1_init(struct t1_state *t1)
658 {
659     t1_clear_states(t1);
660 
661     t1->chk_algo = CHECKSUM_LRC;
662     t1->ifsc     = 32;
663     t1->ifsd     = 32;
664     t1->bwt      = 300; /* milliseconds */
665 
666     t1->send.next = 0;
667     t1->recv.next = 0;
668 
669     t1->need_reset = 1;
670     t1->need_resync = 0;
671     t1->spi_fd     = -1;
672 
673     t1->wtx_max_rounds = MAX_WTX_ROUNDS;
674     t1->wtx_max_value  = 1;
675 
676     t1->recv_max  = 65536 + 2; /* Maximum for extended APDU response */
677     t1->recv_size = 0;
678 }
679 
680 static void
t1_release(struct t1_state * t1)681 t1_release(struct t1_state *t1)
682 {
683     t1->state.halt = 1;
684 }
685 
686 static void
t1_bind(struct t1_state * t1,int src,int dst)687 t1_bind(struct t1_state *t1, int src, int dst)
688 {
689     src &= 7;
690     dst &= 7;
691 
692     t1->nad  = src | (dst << 4);
693     t1->nadc = dst | (src << 4);
694 }
695 
696 static int
697 t1_reset(struct t1_state *t1);
698 
699 static int
t1_transceive(struct t1_state * t1,const void * snd_buf,size_t snd_len,void * rcv_buf,size_t rcv_len)700 t1_transceive(struct t1_state *t1, const void *snd_buf,
701               size_t snd_len, void *rcv_buf, size_t rcv_len)
702 {
703     int n, r;
704 
705     t1_clear_states(t1);
706 
707     t1_init_send_window(t1, snd_buf, snd_len);
708     t1_init_recv_window(t1, rcv_buf, rcv_len);
709 
710     n = t1_loop(t1);
711     if (n == 0)
712         /* Received APDU response */
713         n = (int)t1_recv_window_size(t1);
714     else if (n < 0  && t1->state.aborted != 1){
715         if (!(t1->state.request == 1 && t1->request == T1_REQUEST_RESET))
716         {
717             /*Request Soft RESET to the secure element*/
718             r = t1_reset(t1);
719             if (r < 0) n = -0xDEAD; /*Fatal error meaning eSE is not responding to reset*/
720         }
721     }
722     return n;
723 }
724 
725 static int
t1_negotiate_ifsd(struct t1_state * t1,int ifsd)726 t1_negotiate_ifsd(struct t1_state *t1, int ifsd)
727 {
728     t1_clear_states(t1);
729     t1->state.request = 1;
730 
731     t1->request = T1_REQUEST_IFS;
732     t1->ifsd    = ifsd;
733     return t1_loop(t1);
734 }
735 
736 static int
t1_reset(struct t1_state * t1)737 t1_reset(struct t1_state *t1)
738 {
739     t1_clear_states(t1);
740     t1->need_reset = 1;
741 
742     return t1_loop(t1);
743 }
744 
745 static int
t1_resync(struct t1_state * t1)746 t1_resync(struct t1_state *t1)
747 {
748     t1_clear_states(t1);
749     t1->need_resync = 1;
750 
751     return t1_loop(t1);
752 }
753 
754 void
isot1_init(struct t1_state * t1)755 isot1_init(struct t1_state *t1)
756 {
757     return t1_init(t1);
758 }
759 
760 void
isot1_release(struct t1_state * t1)761 isot1_release(struct t1_state *t1)
762 {
763     t1_release(t1);
764 }
765 
766 void
isot1_bind(struct t1_state * t1,int src,int dst)767 isot1_bind(struct t1_state *t1, int src, int dst)
768 {
769     t1_bind(t1, src, dst);
770 }
771 
772 int
isot1_transceive(struct t1_state * t1,const void * snd_buf,size_t snd_len,void * rcv_buf,size_t rcv_len)773 isot1_transceive(struct t1_state *t1, const void *snd_buf,
774                  size_t snd_len, void *rcv_buf, size_t rcv_len)
775 {
776     return t1_transceive(t1, snd_buf, snd_len, rcv_buf, rcv_len);
777 }
778 
779 int
isot1_negotiate_ifsd(struct t1_state * t1,int ifsd)780 isot1_negotiate_ifsd(struct t1_state *t1, int ifsd)
781 {
782     return t1_negotiate_ifsd(t1, ifsd);
783 }
784 
785 int
isot1_reset(struct t1_state * t1)786 isot1_reset(struct t1_state *t1)
787 {
788     return t1_reset(t1);
789 }
790 
791 int
isot1_resync(struct t1_state * t1)792 isot1_resync(struct t1_state *t1)
793 {
794     return t1_resync(t1);
795 }
796 
797 int
isot1_get_atr(struct t1_state * t1,void * atr,size_t n)798 isot1_get_atr(struct t1_state *t1, void *atr, size_t n)
799 {
800     int r = 0;
801 
802     if (t1->need_reset)
803         r = t1_reset(t1);
804     if (r >= 0) {
805         if (t1->atr_length <= n) {
806             r = t1->atr_length;
807             memcpy(atr, t1->atr, r);
808         } else
809             r = -EFAULT;
810     }
811     return r;
812 }
813