blob: bb5c2036e11cc6c5213c2da174056a63c264febc [file] [log] [blame]
Harald Welte9d3e3822015-11-09 00:50:54 +01001/* ISO7816-3 state machine for the card side */
2/* (C) 2010-2015 by Harald Welte <hwelte@hmw-consulting.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
Harald Welte4c473da2015-11-14 13:31:11 +010020#include <assert.h>
Harald Welte9d3e3822015-11-09 00:50:54 +010021#include <errno.h>
22#include <string.h>
23#include <stdint.h>
24#include <sys/types.h>
25
26#include "utils.h"
27#include "trace.h"
28#include "iso7816_fidi.h"
29#include "tc_etu.h"
30#include "card_emu.h"
31#include "req_ctx.h"
32#include "cardemu_prot.h"
33
34
35#define NUM_SLOTS 2
36
37#define ISO7816_3_INIT_WTIME 9600
38#define ISO7816_3_DEFAULT_WI 10
39#define ISO7816_3_ATR_LEN_MAX (1+32) /* TS plus 32 chars */
40
41#define ISO7816_3_PB_NULL 0x60
42
43enum iso7816_3_card_state {
44 ISO_S_WAIT_POWER, /* waiting for power being applied */
45 ISO_S_WAIT_CLK, /* waiting for clock being applied */
46 ISO_S_WAIT_RST, /* waiting for reset being released */
47 ISO_S_WAIT_ATR, /* waiting for start of ATR */
48 ISO_S_IN_ATR, /* transmitting ATR to reader */
49 ISO_S_IN_PTS, /* transmitting ATR to reader */
50 ISO_S_WAIT_TPDU, /* waiting for data from reader */
51 ISO_S_IN_TPDU, /* inside a TPDU */
52};
53
54/* detailed sub-states of ISO_S_IN_PTS */
55enum pts_state {
56 PTS_S_WAIT_REQ_PTSS,
57 PTS_S_WAIT_REQ_PTS0,
58 PTS_S_WAIT_REQ_PTS1,
59 PTS_S_WAIT_REQ_PTS2,
60 PTS_S_WAIT_REQ_PTS3,
61 PTS_S_WAIT_REQ_PCK,
62 PTS_S_WAIT_RESP_PTSS = PTS_S_WAIT_REQ_PTSS | 0x10,
63 PTS_S_WAIT_RESP_PTS0 = PTS_S_WAIT_REQ_PTS0 | 0x10,
64 PTS_S_WAIT_RESP_PTS1 = PTS_S_WAIT_REQ_PTS1 | 0x10,
65 PTS_S_WAIT_RESP_PTS2 = PTS_S_WAIT_REQ_PTS2 | 0x10,
66 PTS_S_WAIT_RESP_PTS3 = PTS_S_WAIT_REQ_PTS3 | 0x10,
67 PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
68};
69
70#define _PTSS 0
71#define _PTS0 1
72#define _PTS1 2
73#define _PTS2 3
74#define _PTS3 4
75#define _PCK 5
76
Harald Welte16cf4082015-11-11 19:02:48 +010077/* T-PDU state machine states */
Harald Welte9d3e3822015-11-09 00:50:54 +010078enum tpdu_state {
Harald Welte16cf4082015-11-11 19:02:48 +010079 TPDU_S_WAIT_CLA, /* waiting for CLA byte from reader */
80 TPDU_S_WAIT_INS, /* waiting for INS byte from reader */
81 TPDU_S_WAIT_P1, /* waiting for P1 byte from reader */
82 TPDU_S_WAIT_P2, /* waiting for P2 byte from reader */
83 TPDU_S_WAIT_P3, /* waiting for P3 byte from reader */
Harald Welte9d3e3822015-11-09 00:50:54 +010084 TPDU_S_WAIT_PB, /* waiting for Tx of procedure byte */
85 TPDU_S_WAIT_RX, /* waiitng for more data from reader */
86 TPDU_S_WAIT_TX, /* waiting for more data to reader */
87};
88
89#define _CLA 0
90#define _INS 1
91#define _P1 2
92#define _P2 3
93#define _P3 4
94
95struct card_handle {
96 enum iso7816_3_card_state state;
97
98 /* signal levels */
99 uint8_t vcc_active; /* 1 = on, 0 = off */
100 uint8_t in_reset; /* 1 = RST low, 0 = RST high */
101 uint8_t clocked; /* 1 = active, 0 = inactive */
102
Harald Welte16cf4082015-11-11 19:02:48 +0100103 /* timing parameters, from PTS */
Harald Welte9d3e3822015-11-09 00:50:54 +0100104 uint8_t fi;
105 uint8_t di;
106 uint8_t wi;
107
108 uint8_t tc_chan; /* TC channel number */
109 uint8_t uart_chan; /* UART channel */
110
111 uint32_t waiting_time; /* in clocks */
112
113 /* ATR state machine */
114 struct {
115 uint8_t idx;
116 uint8_t len;
117 //uint8_t hist_len;
118 //uint8_t last_td;
119 uint8_t atr[ISO7816_3_ATR_LEN_MAX];
120 } atr;
121
122 /* PPS / PTS support */
123 struct {
124 enum pts_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100125 uint8_t req[6]; /* request bytes */
126 uint8_t resp[6]; /* response bytes */
Harald Welte9d3e3822015-11-09 00:50:54 +0100127 } pts;
128
129 /* TPDU */
130 struct {
131 enum tpdu_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100132 uint8_t hdr[5]; /* CLA INS P1 P2 P3 */
Harald Welte9d3e3822015-11-09 00:50:54 +0100133 } tpdu;
134
Harald Welte16cf4082015-11-11 19:02:48 +0100135 struct req_ctx *uart_rx_ctx; /* UART RX -> USB TX */
136 struct req_ctx *uart_tx_ctx; /* USB RX -> UART TX */
Harald Welte9d3e3822015-11-09 00:50:54 +0100137
138 struct {
139 uint32_t tx_bytes;
140 uint32_t rx_bytes;
141 uint32_t pps;
142 } stats;
143};
144
Harald Welte2935b3c2015-11-14 20:00:14 +0100145static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts);
146
Harald Welte612d65a2015-11-14 13:30:43 +0100147static void update_fidi(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100148{
149 int rc;
150
151 rc = compute_fidi_ratio(ch->fi, ch->di);
152 if (rc > 0 && rc < 0x400) {
153 TRACE_DEBUG("computed Fi(%u) Di(%u) ratio: %d\n",
154 ch->fi, ch->di, rc);
155 /* make sure UART uses new F/D ratio */
156 card_emu_uart_update_fidi(ch->uart_chan, rc);
157 /* notify ETU timer about this */
158 tc_etu_set_etu(ch->tc_chan, rc);
159 } else
160 TRACE_DEBUG("computed FiDi ration %d unsupported\n", rc);
161}
162
163/* Update the ISO 7816-3 TPDU receiver state */
164static void card_set_state(struct card_handle *ch,
165 enum iso7816_3_card_state new_state)
166{
167 switch (new_state) {
168 case ISO_S_WAIT_POWER:
169 case ISO_S_WAIT_CLK:
170 case ISO_S_WAIT_RST:
171 /* disable Rx and Tx of UART */
172 card_emu_uart_enable(ch->uart_chan, 0);
173 break;
174 case ISO_S_WAIT_ATR:
175 /* Reset to initial Fi / Di ratio */
176 ch->fi = 1;
177 ch->di = 1;
178 update_fidi(ch);
179 /* initialize todefault WI, this will be overwritten if we
180 * receive TC2, and it will be programmed into hardware after
181 * ATR is finished */
182 ch->wi = ISO7816_3_DEFAULT_WI;
183 /* update waiting time to initial waiting time */
184 ch->waiting_time = ISO7816_3_INIT_WTIME;
185 tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
186 /* Set ATR sub-state to initial state */
187 ch->atr.idx = 0;
188 //set_atr_state(ch, ATR_S_WAIT_TS);
189 /* Notice that we are just coming out of reset */
190 //ch->sh.flags |= SIMTRACE_FLAG_ATR;
191 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
192 break;
193 break;
194 case ISO_S_WAIT_TPDU:
195 /* enable the receiver, disable transmitter */
Harald Welte2935b3c2015-11-14 20:00:14 +0100196 set_tpdu_state(ch, TPDU_S_WAIT_CLA);
Harald Welte9d3e3822015-11-09 00:50:54 +0100197 card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
198 break;
199 case ISO_S_IN_ATR:
200 case ISO_S_IN_PTS:
201 case ISO_S_IN_TPDU:
202 /* do nothing */
203 break;
204 }
205
206 if (ch->state == new_state)
207 return;
208
209 TRACE_DEBUG("7816 card state %u -> %u\n", ch->state, new_state);
210 ch->state = new_state;
211}
212
213
214/**********************************************************************
215 * PTS / PPS handling
216 **********************************************************************/
217
218/* Update the ATR sub-state */
219static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss)
220{
221 TRACE_DEBUG("7816 PTS state %u -> %u\n", ch->pts.state, new_ptss);
222 ch->pts.state = new_ptss;
223}
224
225/* Determine the next PTS state */
226static enum pts_state next_pts_state(struct card_handle *ch)
227{
228 uint8_t is_resp = ch->pts.state & 0x10;
229 uint8_t sstate = ch->pts.state & 0x0f;
230 uint8_t *pts_ptr;
231
232 if (!is_resp)
233 pts_ptr = ch->pts.req;
234 else
235 pts_ptr = ch->pts.resp;
236
237 switch (sstate) {
238 case PTS_S_WAIT_REQ_PTSS:
239 goto from_ptss;
240 case PTS_S_WAIT_REQ_PTS0:
241 goto from_pts0;
242 case PTS_S_WAIT_REQ_PTS1:
243 goto from_pts1;
244 case PTS_S_WAIT_REQ_PTS2:
245 goto from_pts2;
246 case PTS_S_WAIT_REQ_PTS3:
247 goto from_pts3;
248 }
249
250 if (ch->pts.state == PTS_S_WAIT_REQ_PCK)
251 return PTS_S_WAIT_RESP_PTSS;
252
253from_ptss:
254 return PTS_S_WAIT_REQ_PTS0 | is_resp;
255from_pts0:
256 if (pts_ptr[_PTS0] & (1 << 4))
257 return PTS_S_WAIT_REQ_PTS1 | is_resp;
258from_pts1:
259 if (pts_ptr[_PTS0] & (1 << 5))
260 return PTS_S_WAIT_REQ_PTS2 | is_resp;
261from_pts2:
262 if (pts_ptr[_PTS0] & (1 << 6))
263 return PTS_S_WAIT_REQ_PTS3 | is_resp;
264from_pts3:
265 return PTS_S_WAIT_REQ_PCK | is_resp;
266}
267
268
269static enum iso7816_3_card_state
270process_byte_pts(struct card_handle *ch, uint8_t byte)
271{
272 switch (ch->pts.state) {
273 case PTS_S_WAIT_REQ_PTSS:
274 ch->pts.req[_PTSS] = byte;
275 break;
276 case PTS_S_WAIT_REQ_PTS0:
277 ch->pts.req[_PTS0] = byte;
278 break;
279 case PTS_S_WAIT_REQ_PTS1:
280 ch->pts.req[_PTS1] = byte;
281 break;
282 case PTS_S_WAIT_REQ_PTS2:
283 ch->pts.req[_PTS2] = byte;
284 break;
285 case PTS_S_WAIT_REQ_PTS3:
286 ch->pts.req[_PTS3] = byte;
287 break;
288 case PTS_S_WAIT_REQ_PCK:
289 ch->pts.req[_PCK] = byte;
290 /* FIXME: check PCK */
291 memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
292 break;
Harald Welte4c473da2015-11-14 13:31:11 +0100293 default:
294 TRACE_DEBUG("process_byte_pts() in invalid state %u\n",
295 ch->pts.state);
296 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100297 }
298 /* calculate the next state and set it */
299 set_pts_state(ch, next_pts_state(ch));
300
301 return ISO_S_IN_PTS;
302}
303
304/* return a single byte to be transmitted to the reader */
Harald Welted79dc4f2015-11-14 13:32:21 +0100305static int get_byte_pts(struct card_handle *ch, uint8_t *byte)
Harald Welte9d3e3822015-11-09 00:50:54 +0100306{
Harald Welte9d3e3822015-11-09 00:50:54 +0100307 switch (ch->pts.state) {
308 case PTS_S_WAIT_RESP_PTSS:
Harald Welted79dc4f2015-11-14 13:32:21 +0100309 *byte = ch->pts.resp[_PTSS];
Harald Welte9d3e3822015-11-09 00:50:54 +0100310 break;
311 case PTS_S_WAIT_RESP_PTS0:
Harald Welted79dc4f2015-11-14 13:32:21 +0100312 *byte = ch->pts.resp[_PTS0];
Harald Welte9d3e3822015-11-09 00:50:54 +0100313 break;
314 case PTS_S_WAIT_RESP_PTS1:
Harald Welted79dc4f2015-11-14 13:32:21 +0100315 *byte = ch->pts.resp[_PTS1];
Harald Welte9d3e3822015-11-09 00:50:54 +0100316 /* This must be TA1 */
Harald Welted79dc4f2015-11-14 13:32:21 +0100317 ch->fi = *byte >> 4;
318 ch->di = *byte & 0xf;
Harald Welte9d3e3822015-11-09 00:50:54 +0100319 TRACE_DEBUG("found Fi=%u Di=%u\n", ch->fi, ch->di);
Harald Welted79dc4f2015-11-14 13:32:21 +0100320 //ch->sh.flags |= SIMTRACE_FLAG_PPS_FIDI;
Harald Welte9d3e3822015-11-09 00:50:54 +0100321 break;
322 case PTS_S_WAIT_RESP_PTS2:
Harald Welted79dc4f2015-11-14 13:32:21 +0100323 *byte = ch->pts.resp[_PTS2];
Harald Welte9d3e3822015-11-09 00:50:54 +0100324 break;
325 case PTS_S_WAIT_RESP_PTS3:
Harald Welted79dc4f2015-11-14 13:32:21 +0100326 *byte = ch->pts.resp[_PTS3];
Harald Welte9d3e3822015-11-09 00:50:54 +0100327 break;
328 case PTS_S_WAIT_RESP_PCK:
Harald Welted79dc4f2015-11-14 13:32:21 +0100329 *byte = ch->pts.resp[_PCK];
Harald Welte9d3e3822015-11-09 00:50:54 +0100330 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
331 /* update baud rate generator with Fi/Di */
332 update_fidi(ch);
333 /* Wait for the next TPDU */
334 card_set_state(ch, ISO_S_WAIT_TPDU);
Harald Welted79dc4f2015-11-14 13:32:21 +0100335 default:
336 TRACE_DEBUG("get_byte_pts() in invalid state %u\n",
337 ch->pts.state);
338 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100339 }
Harald Welted79dc4f2015-11-14 13:32:21 +0100340
Harald Welte9d3e3822015-11-09 00:50:54 +0100341 /* calculate the next state and set it */
342 set_pts_state(ch, next_pts_state(ch));
343
344 return 0;
345}
346
347
348/**********************************************************************
349 * TPDU handling
350 **********************************************************************/
351
352/* add a just-received TPDU byte (from reader) to USB buffer */
353static void add_tpdu_byte(struct card_handle *ch, uint8_t byte)
354{
355 struct req_ctx *rctx;
356 struct cardemu_usb_msg_rx_data *rd;
357
358 /* ensure we have a buffer */
359 if (!ch->uart_rx_ctx) {
360 ch->uart_rx_ctx = req_ctx_find_get(1, RCTX_S_FREE, RCTX_S_UART_RX_BUSY);
361 if (!ch->uart_rx_ctx)
362 return;
363 rd = (struct cardemu_usb_msg_rx_data *) ch->uart_rx_ctx->data;
364 cardemu_hdr_set(&rd->hdr, CEMU_USB_MSGT_DO_RX_DATA);
365 rctx->tot_len = sizeof(*rd);
366 rctx->idx = 0;
367 } else
368 rctx = ch->uart_rx_ctx;
369
370 rd = (struct cardemu_usb_msg_rx_data *) rctx->data;
371
372 rd->data[rctx->idx++] = byte;
373 rctx->tot_len++;
374
375 /* check if the buffer is full. If so, send it */
376 if (rctx->tot_len >= rctx->size) {
377 /* store length of data payload fild in header */
378 rd->hdr.data_len = rctx->idx;
379 req_ctx_set_state(rctx, RCTX_S_USB_TX_PENDING);
380 ch->uart_rx_ctx = NULL;
381 /* FIXME: call into USB code to see if this buffer can
382 * be transmitted now */
383 }
384}
385
386static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts)
387{
388 TRACE_DEBUG("7816 TPDU state %u -> %u\n", ch->tpdu.state, new_ts);
389 switch (new_ts) {
390 case TPDU_S_WAIT_CLA:
391 card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
392 break;
393 case TPDU_S_WAIT_PB:
394 /* we just completed the TPDU header from reader to card
395 * and now need to disable the receiver, enable the
396 * transmitter and transmit the procedure byte */
397 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
398 break;
399 }
400 ch->tpdu.state = new_ts;
401}
402
403static enum tpdu_state next_tpdu_state(struct card_handle *ch)
404{
405 switch (ch->tpdu.state) {
406 case TPDU_S_WAIT_CLA:
407 return TPDU_S_WAIT_INS;
408 case TPDU_S_WAIT_INS:
409 return TPDU_S_WAIT_P1;
410 case TPDU_S_WAIT_P1:
411 return TPDU_S_WAIT_P2;
412 case TPDU_S_WAIT_P2:
413 return TPDU_S_WAIT_P3;
414 case TPDU_S_WAIT_P3:
415 return TPDU_S_WAIT_PB;
416 /* simply stay in Rx or Tx by default */
417 case TPDU_S_WAIT_PB:
418 return TPDU_S_WAIT_PB;
419 case TPDU_S_WAIT_RX:
420 return TPDU_S_WAIT_RX;
421 case TPDU_S_WAIT_TX:
422 return TPDU_S_WAIT_TX;
423 }
Harald Welte4c473da2015-11-14 13:31:11 +0100424 /* we should never reach here */
425 assert(0);
426 return -1;
Harald Welte9d3e3822015-11-09 00:50:54 +0100427}
428
429static void send_tpdu_header(struct card_handle *ch)
430{
431 struct req_ctx *rctx;
432 struct cardemu_usb_msg_rx_data *rd;
433
434 /* if we already/still have a context, send it off */
Harald Welte2935b3c2015-11-14 20:00:14 +0100435 if (ch->uart_rx_ctx && ch->uart_rx_ctx->idx) {
436 /* FIXME: do we need to initialize the USB protocol
437 * header? .... */
438 req_ctx_set_state(ch->uart_rx_ctx, RCTX_S_USB_TX_PENDING);
Harald Welte9d3e3822015-11-09 00:50:54 +0100439 ch->uart_rx_ctx = NULL;
440 }
441
442 /* ensure we have a new buffer */
443 ch->uart_rx_ctx = req_ctx_find_get(1, RCTX_S_FREE, RCTX_S_UART_RX_BUSY);
444 if (!ch->uart_rx_ctx)
445 return;
446 rctx = ch->uart_rx_ctx;
447 rd = (struct cardemu_usb_msg_rx_data *) rctx->data;
448
449 /* initializ header */
450 cardemu_hdr_set(&rd->hdr, CEMU_USB_MSGT_DO_RX_DATA);
451 rd->flags = CEMU_DATA_F_TPDU_HDR;
452 rctx->tot_len = sizeof(*rd) + sizeof(ch->tpdu.hdr);
453 rctx->idx = 0;
454
455 /* copy TPDU header to data field */
456 memcpy(rd->data, ch->tpdu.hdr, sizeof(ch->tpdu.hdr));
457 rd->hdr.data_len = sizeof(ch->tpdu.hdr);
458
459 req_ctx_set_state(rctx, RCTX_S_USB_TX_PENDING);
460}
461
462static enum iso7816_3_card_state
463process_byte_tpdu(struct card_handle *ch, uint8_t byte)
464{
465 switch (ch->tpdu.state) {
466 case TPDU_S_WAIT_CLA:
467 ch->tpdu.hdr[_CLA] = byte;
468 break;
469 case TPDU_S_WAIT_INS:
470 ch->tpdu.hdr[_INS] = byte;
471 break;
472 case TPDU_S_WAIT_P1:
473 ch->tpdu.hdr[_P1] = byte;
474 break;
475 case TPDU_S_WAIT_P2:
476 ch->tpdu.hdr[_P2] = byte;
477 break;
478 case TPDU_S_WAIT_P3:
479 ch->tpdu.hdr[_P3] = byte;
480 /* FIXME: start timer to transmit further 0x60 */
481 /* send the TPDU header as part of a procedure byte
482 * request to the USB host */
483 send_tpdu_header(ch);
484 break;
485 case TPDU_S_WAIT_RX:
486 add_tpdu_byte(ch, byte);
487 break;
488 default:
489 TRACE_DEBUG("process_byte_tpdu() in invalid state %u\n",
490 ch->tpdu.state);
491 }
492 set_tpdu_state(ch, next_tpdu_state(ch));
493
494 /* ensure we stay in TPDU ISO state */
495 return ISO_S_IN_TPDU;
496}
497
498/* return a single byte to be transmitted to the reader */
499static int get_byte_tpdu(struct card_handle *ch, uint8_t *byte)
500{
501 struct req_ctx *rctx;
502 struct cardemu_usb_msg_tx_data *td;
503
504 /* ensure we are aware of any data that might be pending for
505 * transmit */
506 if (!ch->uart_tx_ctx) {
507 ch->uart_tx_ctx = req_ctx_find_get(1, RCTX_S_UART_TX_PENDING,
508 RCTX_S_UART_TX_BUSY);
509 if (!ch->uart_tx_ctx)
510 return 0;
511
512 /* start with index zero */
513 ch->uart_tx_ctx->idx = 0;
514
515 }
516 rctx = ch->uart_tx_ctx;
517 td = (struct cardemu_usb_msg_tx_data *) rctx->data;
518
519#if 0
520 /* this must happen _after_ the byte has been transmittd */
521 switch (ch->tpdu.state) {
522 case TPDU_S_WAIT_PB:
523 if (td->flags & CEMU_DATA_F_PB_AND_TX)
524 set_tpdu_state(ch, TPDU_S_WAIT_TX);
525 else if (td->flags & CEMU_DATA_F_PB_AND_RX)
526 set_tpdu_state(ch, TPDU_S_WAIT_RX);
527 break;
528 }
529#endif
530
531 /* take the next pending byte out of the rctx */
532 *byte = td->data[rctx->idx++];
533
534 /* check if the buffer has now been fully transmitted */
535 if ((rctx->idx >= td->hdr.data_len) ||
536 (rctx->idx + sizeof(*td) - sizeof(td->hdr) >= rctx->tot_len)) {
Harald Welte2935b3c2015-11-14 20:00:14 +0100537 if (td->flags & CEMU_DATA_F_FINAL) {
538 /* this was the final part of the APDU, go
539 * back to state one*/
540 card_set_state(ch, ISO_S_WAIT_TPDU);
541 } else {
542 /* FIXME: call into USB code to chec if we need
543 * to submit a free buffer to accept furthe data
544 * on bulk out endpoint */
545 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100546 req_ctx_set_state(rctx, RCTX_S_FREE);
547 ch->uart_tx_ctx = NULL;
Harald Welte9d3e3822015-11-09 00:50:54 +0100548 }
549
550 return 1;
551}
552
553/**********************************************************************
554 * Public API
555 **********************************************************************/
556
557/* process a single byte received from the reader */
558void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
559{
560 int new_state = -1;
561
562 ch->stats.rx_bytes++;
563
564 switch (ch->state) {
565 case ISO_S_WAIT_POWER:
566 case ISO_S_WAIT_CLK:
567 case ISO_S_WAIT_RST:
568 case ISO_S_WAIT_ATR:
569 /* we shouldn't receive any data from the reader yet! */
570 break;
571 case ISO_S_WAIT_TPDU:
572 if (byte == 0xff) {
573 new_state = process_byte_pts(ch, byte);
574 ch->stats.pps++;
575 goto out_silent;
576 }
577 /* fall-through */
578 case ISO_S_IN_TPDU:
579 new_state = process_byte_tpdu(ch, byte);
580 break;
581 case ISO_S_IN_PTS:
582 new_state = process_byte_pts(ch, byte);
583 goto out_silent;
584 }
585
586out_silent:
587 if (new_state != -1)
588 card_set_state(ch, new_state);
589}
590
591/* return a single byte to be transmitted to the reader */
592int card_emu_get_tx_byte(struct card_handle *ch, uint8_t *byte)
593{
594 int rc = 0;
595
596 switch (ch->state) {
597 case ISO_S_IN_ATR:
598 if (ch->atr.idx < ch->atr.len) {
599 *byte = ch->atr.atr[ch->atr.idx++];
600 rc = 1;
601 /* detect end of ATR */
602 if (ch->atr.idx >= ch->atr.len)
603 card_set_state(ch, ISO_S_WAIT_TPDU);
604 }
605 break;
606 case ISO_S_IN_PTS:
Harald Welted79dc4f2015-11-14 13:32:21 +0100607 rc = get_byte_pts(ch, byte);
Harald Welte9d3e3822015-11-09 00:50:54 +0100608 break;
609 case ISO_S_IN_TPDU:
610 rc = get_byte_tpdu(ch, byte);
611 break;
612 }
613
614 if (rc)
615 ch->stats.tx_bytes++;
616
617 return rc;
618}
619
620/* hardware driver informs us that a card I/O signal has changed */
621void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
622{
623 switch (io) {
624 case CARD_IO_VCC:
625 if (active == 0)
626 card_set_state(ch, ISO_S_WAIT_POWER);
627 else if (active == 1 && ch->vcc_active == 0)
628 card_set_state(ch, ISO_S_WAIT_CLK);
629 ch->vcc_active = active;
630 break;
631 case CARD_IO_CLK:
632 if (active == 1 && ch->state == ISO_S_WAIT_CLK)
633 card_set_state(ch, ISO_S_WAIT_RST);
634 ch->clocked = active;
635 break;
636 case CARD_IO_RST:
637 if (active == 0 && ch->in_reset &&
638 ch->vcc_active && ch->clocked) {
639 /* FIXME: wait 400 clocks */
640 //card_set_state(ch, ISO_S_WAIT_ATR);
641 card_set_state(ch, ISO_S_IN_ATR);
642 }
643 ch->in_reset = active;
644 break;
645 }
646}
647
648/* User sets a new ATR to be returned during next card reset */
649int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
650{
651 if (len > sizeof(ch->atr.atr))
652 return -1;
653
654 memcpy(ch->atr.atr, atr, len);
655 ch->atr.len = len;
656 ch->atr.idx = 0;
657
658 /* FIXME: race condition with trasmitting ATR to reader? */
659
660 return 0;
661}
662
663/* hardware driver informs us that one (more) ETU has expired */
664void tc_etu_wtime_half_expired(void *handle)
665{
666 struct card_handle *ch = handle;
667 /* transmit NULL procedure byte well before waiting time expires */
668 card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);
669}
670
671/* hardware driver informs us that one (more) ETU has expired */
672void tc_etu_wtime_expired(void *handle)
673{
674}
675
676/* shortest ATR found in smartcard_list.txt */
677static const uint8_t default_atr[] = { 0x3B, 0x02, 0x14, 0x50 };
678
679static struct card_handle card_handles[NUM_SLOTS];
680
681struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan)
682{
683 struct card_handle *ch;
684
685 if (slot_num >= ARRAY_SIZE(card_handles))
686 return NULL;
687
688 ch = &card_handles[slot_num];
689
690 memset(ch, 0, sizeof(*ch));
691
692 /* initialize the card_handle with reasonabe defaults */
693 ch->state = ISO_S_WAIT_POWER;
694 ch->vcc_active = 0;
695 ch->in_reset = 1;
696 ch->clocked = 0;
697
698 ch->fi = 0;
699 ch->di = 1;
700 ch->wi = ISO7816_3_DEFAULT_WI;
701
702 ch->tc_chan = tc_chan;
703 ch->uart_chan = uart_chan;
704 ch->waiting_time = ISO7816_3_INIT_WTIME;
705
706 ch->atr.idx = 0;
707 ch->atr.len = sizeof(default_atr);
708 memcpy(ch->atr.atr, default_atr, ch->atr.len);
709
710 ch->pts.state = PTS_S_WAIT_REQ_PTSS;
711 ch->tpdu.state = TPDU_S_WAIT_CLA;
712
713 tc_etu_init(ch->tc_chan, ch);
714
715 return ch;
716}