blob: f861b636a9f722931b2c3321e49c14f69adebb62 [file] [log] [blame]
Kévin Redon9a12d682018-07-08 13:21:16 +02001/* ISO7816-3 state machine for the card side
Harald Welte9d3e3822015-11-09 00:50:54 +01002 *
Kévin Redon9a12d682018-07-08 13:21:16 +02003 * (C) 2010-2017 by Harald Welte <laforge@gnumonks.org>
Kévin Redon76c2eeb2019-06-13 15:41:52 +02004 * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
Harald Welte9d3e3822015-11-09 00:50:54 +01005 *
Kévin Redon9a12d682018-07-08 13:21:16 +02006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
Harald Welte9d3e3822015-11-09 00:50:54 +010010 *
Kévin Redon9a12d682018-07-08 13:21:16 +020011 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Harald Welte9d3e3822015-11-09 00:50:54 +010015 *
Kévin Redon9a12d682018-07-08 13:21:16 +020016 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Harald Welte9d3e3822015-11-09 00:50:54 +010019 */
Harald Weltec430ac12017-02-28 01:25:12 +010020#include <stdio.h>
Harald Welte4c473da2015-11-14 13:31:11 +010021#include <assert.h>
Harald Welte9d3e3822015-11-09 00:50:54 +010022#include <errno.h>
23#include <string.h>
24#include <stdint.h>
25#include <sys/types.h>
26
27#include "utils.h"
28#include "trace.h"
Kévin Redon76c2eeb2019-06-13 15:41:52 +020029#include "iso7816_3.h"
Harald Welte9d3e3822015-11-09 00:50:54 +010030#include "card_emu.h"
Harald Welte25a9a802017-05-08 13:30:09 +020031#include "simtrace_prot.h"
Harald Welte8e7fca32017-05-07 16:14:33 +020032#include "usb_buf.h"
Harald Welte9d90d282018-06-29 22:25:42 +020033#include <osmocom/core/linuxlist.h>
34#include <osmocom/core/msgb.h>
Harald Welte9d3e3822015-11-09 00:50:54 +010035
Harald Welte9d3e3822015-11-09 00:50:54 +010036#define NUM_SLOTS 2
37
38#define ISO7816_3_INIT_WTIME 9600
39#define ISO7816_3_DEFAULT_WI 10
40#define ISO7816_3_ATR_LEN_MAX (1+32) /* TS plus 32 chars */
41
42#define ISO7816_3_PB_NULL 0x60
43
44enum iso7816_3_card_state {
45 ISO_S_WAIT_POWER, /* waiting for power being applied */
46 ISO_S_WAIT_CLK, /* waiting for clock being applied */
47 ISO_S_WAIT_RST, /* waiting for reset being released */
48 ISO_S_WAIT_ATR, /* waiting for start of ATR */
49 ISO_S_IN_ATR, /* transmitting ATR to reader */
50 ISO_S_IN_PTS, /* transmitting ATR to reader */
51 ISO_S_WAIT_TPDU, /* waiting for data from reader */
52 ISO_S_IN_TPDU, /* inside a TPDU */
53};
54
Kévin Redon8a4fba52018-08-02 17:44:16 +020055const struct value_string iso7816_3_card_state_names[] = {
Kévin Redon2fdcf3b2018-10-15 19:43:15 +020056 {
57 .value = ISO_S_WAIT_POWER,
58 .str = "WAIT_POWER",
59 },
60 {
61 .value = ISO_S_WAIT_CLK,
62 .str = "WAIT_CLK",
63 },
64 {
65 .value = ISO_S_WAIT_RST,
66 .str = "WAIT_RST",
67 },
68 {
69 .value = ISO_S_WAIT_ATR,
70 .str = "WAIT_ATR",
71 },
72 {
73 .value = ISO_S_IN_ATR,
74 .str = "IN_ATR",
75 },
76 {
77 .value = ISO_S_IN_PTS,
78 .str = "IN_PTS",
79 },
80 {
81 .value = ISO_S_WAIT_TPDU,
82 .str = "WAIT_TPDU",
83 },
84 {
85 .value = ISO_S_IN_TPDU,
86 .str = "IN_TPDU",
87 },
Kévin Redon8a4fba52018-08-02 17:44:16 +020088 {
89 .value = 0,
90 .str = NULL,
91 },
92};
93
94
Harald Welte9d3e3822015-11-09 00:50:54 +010095/* detailed sub-states of ISO_S_IN_PTS */
96enum pts_state {
97 PTS_S_WAIT_REQ_PTSS,
98 PTS_S_WAIT_REQ_PTS0,
99 PTS_S_WAIT_REQ_PTS1,
100 PTS_S_WAIT_REQ_PTS2,
101 PTS_S_WAIT_REQ_PTS3,
102 PTS_S_WAIT_REQ_PCK,
103 PTS_S_WAIT_RESP_PTSS = PTS_S_WAIT_REQ_PTSS | 0x10,
104 PTS_S_WAIT_RESP_PTS0 = PTS_S_WAIT_REQ_PTS0 | 0x10,
105 PTS_S_WAIT_RESP_PTS1 = PTS_S_WAIT_REQ_PTS1 | 0x10,
106 PTS_S_WAIT_RESP_PTS2 = PTS_S_WAIT_REQ_PTS2 | 0x10,
107 PTS_S_WAIT_RESP_PTS3 = PTS_S_WAIT_REQ_PTS3 | 0x10,
108 PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
109};
110
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200111/* PTS field byte index */
Harald Welte9d3e3822015-11-09 00:50:54 +0100112#define _PTSS 0
113#define _PTS0 1
114#define _PTS1 2
115#define _PTS2 3
116#define _PTS3 4
117#define _PCK 5
118
Harald Welte16cf4082015-11-11 19:02:48 +0100119/* T-PDU state machine states */
Harald Welte9d3e3822015-11-09 00:50:54 +0100120enum tpdu_state {
Harald Welte16cf4082015-11-11 19:02:48 +0100121 TPDU_S_WAIT_CLA, /* waiting for CLA byte from reader */
122 TPDU_S_WAIT_INS, /* waiting for INS byte from reader */
123 TPDU_S_WAIT_P1, /* waiting for P1 byte from reader */
124 TPDU_S_WAIT_P2, /* waiting for P2 byte from reader */
125 TPDU_S_WAIT_P3, /* waiting for P3 byte from reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100126 TPDU_S_WAIT_PB, /* waiting for Tx of procedure byte */
Kévin Redon0f4abf52018-08-02 17:42:48 +0200127 TPDU_S_WAIT_RX, /* waiting for more data from reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100128 TPDU_S_WAIT_TX, /* waiting for more data to reader */
129};
130
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200131const struct value_string tpdu_state_names[] = {
132 {
133 .value = TPDU_S_WAIT_CLA,
134 .str = "WAIT_CLA",
135 },
136 {
137 .value = TPDU_S_WAIT_INS,
138 .str = "WAIT_INS",
139 },
140 {
141 .value = TPDU_S_WAIT_P1,
142 .str = "WAIT_P1",
143 },
144 {
145 .value = TPDU_S_WAIT_P2,
146 .str = "WAIT_P2",
147 },
148 {
149 .value = TPDU_S_WAIT_P3,
150 .str = "WAIT_P3",
151 },
152 {
153 .value = TPDU_S_WAIT_PB,
154 .str = "WAIT_PB",
155 },
156 {
157 .value = TPDU_S_WAIT_RX,
158 .str = "WAIT_RX",
159 },
160 {
161 .value = TPDU_S_WAIT_TX,
162 .str = "WAIT_TX",
163 },
164 {
165 .value = 0,
166 .str = NULL,
167 },
168};
169
170/* TPDU field byte index */
Harald Welte9d3e3822015-11-09 00:50:54 +0100171#define _CLA 0
172#define _INS 1
173#define _P1 2
174#define _P2 3
175#define _P3 4
176
177struct card_handle {
Harald Weltec3941092018-08-26 09:53:13 +0200178 unsigned int num;
Harald Weltedde112e2016-03-20 16:42:11 +0100179
Harald Welte9d3e3822015-11-09 00:50:54 +0100180 enum iso7816_3_card_state state;
181
182 /* signal levels */
183 uint8_t vcc_active; /* 1 = on, 0 = off */
184 uint8_t in_reset; /* 1 = RST low, 0 = RST high */
185 uint8_t clocked; /* 1 = active, 0 = inactive */
186
Harald Welte9d3e3822015-11-09 00:50:54 +0100187 uint8_t tc_chan; /* TC channel number */
188 uint8_t uart_chan; /* UART channel */
189
Harald Welte8e7fca32017-05-07 16:14:33 +0200190 uint8_t in_ep; /* USB IN EP */
191 uint8_t irq_ep; /* USB IN EP */
192
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200193 /*! clock rate conversion integer F
194 * @implements ISO/IEC 7816-3:2006(E) section 7.1
195 * @note this represents the current value used
196 */
197 uint16_t f;
198 /*! baud rate adjustment factor D
199 * @implements ISO/IEC 7816-3:2006(E) section 7.1
200 * @note this represents the current value used
201 */
202 uint8_t d;
203 /*! clock frequency in Hz
204 * @implements ISO/IEC 7816-3:2006(E) section 7.1
205 * @note the USART peripheral in slave mode does not provide the current value. we could measure it but this is not really useful. instead we remember the maximum possible value corresponding to the selected F value
206 */
207 uint32_t f_cur;
208 /*! clock rate conversion integer Fi
209 * @implements ISO/IEC 7816-3:2006(E) Table 7
210 * @note this represents the maximum value supported by the card, and can be indicated in TA1
211 * @note this value can be set in TA1
212 */
213 uint16_t fi;
214 /*! baud rate adjustment factor Di
215 * @implements ISO/IEC 7816-3:2006(E) Table 8
216 * @note this represents the maximum value supported by the card, and can be indicated in TA1
217 */
218 uint8_t di;
219 /*! clock frequency, in Hz
220 * @implements ISO/IEC 7816-3:2006(E) Table 7
221 * @note this represents the maximum value supported by the card, and can be indicated in TA1
222 */
223 uint32_t f_max;
224 /*! Waiting Integer
225 * @implements ISO/IEC 7816-3:2006(E) Section 10.2
226 * @note this value can be set in TA2
227 */
228 uint8_t wi;
229 /*! Waiting Time, in ETU
230 * @implements ISO/IEC 7816-3:2006(E) Section 8.1
231 * @note this depends on Fi, Di, and WI if T=0 is used
232 */
233 uint32_t wt;
Harald Welte9d3e3822015-11-09 00:50:54 +0100234
235 /* ATR state machine */
236 struct {
237 uint8_t idx;
238 uint8_t len;
239 //uint8_t hist_len;
240 //uint8_t last_td;
241 uint8_t atr[ISO7816_3_ATR_LEN_MAX];
242 } atr;
243
244 /* PPS / PTS support */
245 struct {
246 enum pts_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100247 uint8_t req[6]; /* request bytes */
248 uint8_t resp[6]; /* response bytes */
Harald Welte9d3e3822015-11-09 00:50:54 +0100249 } pts;
250
251 /* TPDU */
252 struct {
253 enum tpdu_state state;
Harald Welte16cf4082015-11-11 19:02:48 +0100254 uint8_t hdr[5]; /* CLA INS P1 P2 P3 */
Harald Welte9d3e3822015-11-09 00:50:54 +0100255 } tpdu;
256
Harald Welte8e7fca32017-05-07 16:14:33 +0200257 struct msgb *uart_rx_msg; /* UART RX -> USB TX */
258 struct msgb *uart_tx_msg; /* USB RX -> UART TX */
Harald Welte9d3e3822015-11-09 00:50:54 +0100259
Harald Welte54cb3d02016-02-29 14:12:40 +0100260 struct llist_head uart_tx_queue;
261
Harald Welte9d3e3822015-11-09 00:50:54 +0100262 struct {
263 uint32_t tx_bytes;
264 uint32_t rx_bytes;
265 uint32_t pps;
266 } stats;
267};
268
Harald Welte54cb3d02016-02-29 14:12:40 +0100269struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch)
270{
271 return &ch->uart_tx_queue;
272}
273
Harald Welte2935b3c2015-11-14 20:00:14 +0100274static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts);
Harald Weltee7194ab2015-11-14 21:03:25 +0100275static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss);
Harald Welte2935b3c2015-11-14 20:00:14 +0100276
Harald Welte25a9a802017-05-08 13:30:09 +0200277/* update simtrace header msg_len and submit USB buffer */
278void usb_buf_upd_len_and_submit(struct msgb *msg)
279{
Harald Welteb91f6ad2017-05-10 22:51:30 +0200280 struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h;
Harald Welte25a9a802017-05-08 13:30:09 +0200281
282 sh->msg_len = msgb_length(msg);
283
284 usb_buf_submit(msg);
285}
286
287/* Allocate USB buffer and push + initialize simtrace_msg_hdr */
288struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
289{
290 struct msgb *msg;
291 struct simtrace_msg_hdr *sh;
292
293 msg = usb_buf_alloc(ep);
294 if (!msg)
295 return NULL;
296
297 msg->l1h = msgb_put(msg, sizeof(*sh));
298 sh = (struct simtrace_msg_hdr *) msg->l1h;
299 memset(sh, 0, sizeof(*sh));
300 sh->msg_class = msg_class;
301 sh->msg_type = msg_type;
302 msg->l2h = msg->l1h + sizeof(*sh);
303
304 return msg;
305}
306
Kévin Redon680bdab2018-07-18 14:00:57 +0200307/* Update cardemu_usb_msg_rx_data length + submit buffer */
Harald Welteb5288e82015-11-14 21:15:52 +0100308static void flush_rx_buffer(struct card_handle *ch)
309{
Harald Welte8e7fca32017-05-07 16:14:33 +0200310 struct msgb *msg;
Harald Welteb5288e82015-11-14 21:15:52 +0100311 struct cardemu_usb_msg_rx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200312 uint32_t data_len;
Harald Welteb5288e82015-11-14 21:15:52 +0100313
Harald Welte8e7fca32017-05-07 16:14:33 +0200314 msg = ch->uart_rx_msg;
315 if (!msg)
Harald Welteb5288e82015-11-14 21:15:52 +0100316 return;
317
Harald Welte8e7fca32017-05-07 16:14:33 +0200318 ch->uart_rx_msg = NULL;
Harald Welteb5288e82015-11-14 21:15:52 +0100319
Kévin Redon680bdab2018-07-18 14:00:57 +0200320 /* store length of data payload field in header */
Harald Welte25a9a802017-05-08 13:30:09 +0200321 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
322 rd->data_len = msgb_l2len(msg) - sizeof(*rd);
Harald Welte54cb3d02016-02-29 14:12:40 +0100323
Kévin Redon910e6832018-08-02 17:47:57 +0200324 TRACE_INFO("%u: %s (%u)\n\r",
325 ch->num, __func__, rd->data_len);
326
Harald Welte25a9a802017-05-08 13:30:09 +0200327 usb_buf_upd_len_and_submit(msg);
Harald Welteb5288e82015-11-14 21:15:52 +0100328}
329
Kévin Redon680bdab2018-07-18 14:00:57 +0200330/* convert a non-contiguous PTS request/response into a contiguous
Harald Welte4ba66d02016-02-25 19:38:56 +0100331 * buffer, returning the number of bytes used in the buffer */
332static int serialize_pts(uint8_t *out, const uint8_t *in)
333{
334 int i = 0;
335
336 out[i++] = in[_PTSS];
337 out[i++] = in[_PTS0];
338 if (in[_PTS0] & (1 << 4))
339 out[i++] = in[_PTS1];
340 if (in[_PTS0] & (1 << 5))
341 out[i++] = in[_PTS2];
342 if (in[_PTS0] & (1 << 6))
343 out[i++] = in[_PTS3];
344 out[i++] = in[_PCK];
345
346 return i;
347}
348
Harald Welte17db2f12016-02-26 09:48:57 +0100349static uint8_t csum_pts(const uint8_t *in)
350{
351 uint8_t out[6];
352 int len = serialize_pts(out, in);
353 uint8_t csum = 0;
354 int i;
355
356 /* we don't include the PCK byte in the checksumming process */
357 len -= 1;
358
359 for (i = 0; i < len; i++)
360 csum = csum ^ out[i];
361
362 return csum;
363}
364
Harald Welte4ba66d02016-02-25 19:38:56 +0100365static void flush_pts(struct card_handle *ch)
366{
Harald Welte8e7fca32017-05-07 16:14:33 +0200367 struct msgb *msg;
Harald Welte4ba66d02016-02-25 19:38:56 +0100368 struct cardemu_usb_msg_pts_info *ptsi;
369
Harald Welte25a9a802017-05-08 13:30:09 +0200370 msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DO_CEMU_PTS);
Harald Welte8e7fca32017-05-07 16:14:33 +0200371 if (!msg)
Harald Welte4ba66d02016-02-25 19:38:56 +0100372 return;
373
Harald Welte25a9a802017-05-08 13:30:09 +0200374 ptsi = (struct cardemu_usb_msg_pts_info *) msgb_put(msg, sizeof(*ptsi));
Harald Welted295b922016-03-18 21:01:36 +0100375 ptsi->pts_len = serialize_pts(ptsi->req, ch->pts.req);
Harald Welte4ba66d02016-02-25 19:38:56 +0100376 serialize_pts(ptsi->resp, ch->pts.resp);
377
Harald Welte25a9a802017-05-08 13:30:09 +0200378 usb_buf_upd_len_and_submit(msg);
Harald Welte4ba66d02016-02-25 19:38:56 +0100379}
380
Harald Welte9d3e3822015-11-09 00:50:54 +0100381/* Update the ISO 7816-3 TPDU receiver state */
382static void card_set_state(struct card_handle *ch,
383 enum iso7816_3_card_state new_state)
384{
Harald Welte903d63a2016-03-20 13:38:39 +0100385 if (ch->state == new_state)
386 return;
387
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200388 TRACE_DEBUG("%u: 7816 card state %s -> %s\r\n", ch->num,
389 get_value_string(iso7816_3_card_state_names, ch->state),
390 get_value_string(iso7816_3_card_state_names, new_state));
Harald Welte903d63a2016-03-20 13:38:39 +0100391 ch->state = new_state;
392
Harald Welte9d3e3822015-11-09 00:50:54 +0100393 switch (new_state) {
394 case ISO_S_WAIT_POWER:
395 case ISO_S_WAIT_CLK:
396 case ISO_S_WAIT_RST:
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200397 card_emu_uart_enable(ch->uart_chan, 0); // disable Rx and Tx of UART
398 card_emu_uart_update_wt(ch->uart_chan, 0); // disable timeout
399 if (ISO_S_WAIT_POWER == new_state) {
400 card_emu_uart_io_set(ch->uart_chan, false); // pull I/O line low
401 } else {
402 card_emu_uart_io_set(ch->uart_chan, true); // pull I/O line high
403 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100404 break;
405 case ISO_S_WAIT_ATR:
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200406 // reset the ETU-related values
407 ch->f = ISO7816_3_DEFAULT_FD;
408 ch->d = ISO7816_3_DEFAULT_DD;
409 card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set baud rate
410
411 // reset values optionally specified in the ATR
412 ch->fi = ISO7816_3_DEFAULT_FI;
413 ch->di = ISO7816_3_DEFAULT_DI;
414 ch->wi = ISO7816_3_DEFAULT_WI;
415 int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get default waiting time
416 if (wt <= 0) {
417 TRACE_FATAL("%u: invalid WT %ld\r\n", ch->num, wt);
418 }
419 ch->wt = wt;
420 card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // enable TX to be able to use the timeout
Kévin Redonebe672e2018-07-29 00:18:12 +0200421 /* the ATR should only be sent 400 to 40k clock cycles after the RESET.
422 * we use the tc_etu mechanism to wait this time.
423 * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
424 */
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200425 card_emu_uart_update_wt(ch->uart_chan, 2);
Kévin Redonebe672e2018-07-29 00:18:12 +0200426 break;
427 case ISO_S_IN_ATR:
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200428 // FIXME disable timeout while sending ATR
Harald Welte9d3e3822015-11-09 00:50:54 +0100429 /* Set ATR sub-state to initial state */
430 ch->atr.idx = 0;
Kévin Redonebe672e2018-07-29 00:18:12 +0200431 /* enable USART transmission to reader */
Harald Welte9d3e3822015-11-09 00:50:54 +0100432 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
Kévin Redonebe672e2018-07-29 00:18:12 +0200433 /* trigger USART TX IRQ to sent first ATR byte TS */
434 card_emu_uart_interrupt(ch->uart_chan);
Harald Welte9d3e3822015-11-09 00:50:54 +0100435 break;
436 case ISO_S_WAIT_TPDU:
437 /* enable the receiver, disable transmitter */
Harald Welte2935b3c2015-11-14 20:00:14 +0100438 set_tpdu_state(ch, TPDU_S_WAIT_CLA);
Harald Welte9d3e3822015-11-09 00:50:54 +0100439 card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
440 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100441 case ISO_S_IN_PTS:
442 case ISO_S_IN_TPDU:
443 /* do nothing */
444 break;
445 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100446}
447
Kévin Redonebe672e2018-07-29 00:18:12 +0200448/**********************************************************************
449 * ATR handling
450 **********************************************************************/
451
452/*! Transmit ATR data to reader
453 * @param[in] ch card interface connected to reader
454 * @return numbers of bytes transmitted
455 */
456static int tx_byte_atr(struct card_handle *ch)
457{
458 if (NULL == ch) {
459 TRACE_ERROR("ATR TX: no card handle provided\n\r");
460 return 0;
461 }
462 if (ISO_S_IN_ATR != ch->state) {
463 TRACE_ERROR("%u: ATR TX: no in ATR state\n\r", ch->num);
464 return 0;
465 }
466
467 /* Transmit ATR */
468 if (ch->atr.idx < ch->atr.len) {
469 uint8_t byte = ch->atr.atr[ch->atr.idx++];
470 card_emu_uart_tx(ch->uart_chan, byte);
Kévin Redonebe672e2018-07-29 00:18:12 +0200471 return 1;
472 } else { /* The ATR has been completely transmitted */
Kévin Redon8b8e58b2018-07-30 18:19:11 +0200473 /* search for TC2 to updated WI */
Kévin Redon8b8e58b2018-07-30 18:19:11 +0200474 if (ch->atr.len >= 2 && ch->atr.atr[1] & 0xf0) { /* Y1 has some data */
475 uint8_t atr_td1 = 2;
476 if (ch->atr.atr[1] & 0x10) { /* TA1 is present */
477 atr_td1++;
478 }
479 if (ch->atr.atr[1] & 0x20) { /* TB1 is present */
480 atr_td1++;
481 }
482 if (ch->atr.atr[1] & 0x40) { /* TC1 is present */
483 atr_td1++;
484 }
485 if (ch->atr.atr[1] & 0x80) { /* TD1 is present */
486 if (ch->atr.len > atr_td1 && ch->atr.atr[atr_td1] & 0xf0) { /* Y2 has some data */
487 uint8_t atr_tc2 = atr_td1+1;
488 if (ch->atr.atr[atr_td1] & 0x10) { /* TA2 is present */
489 atr_tc2++;
490 }
491 if (ch->atr.atr[atr_td1] & 0x20) { /* TB2 is present */
492 atr_tc2++;
493 }
494 if (ch->atr.atr[atr_td1] & 0x40) { /* TC2 is present */
495 if (ch->atr.len > atr_tc2 && ch->atr.atr[atr_tc2]) { /* TC2 encodes WI */
496 ch->wi = ch->atr.atr[atr_tc2]; /* set WI */
497 }
498 }
499 }
500 }
501 }
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200502 /* FIXME update waiting time in case of card is specific mode */
Kévin Redonebe672e2018-07-29 00:18:12 +0200503 /* reset PTS to initial state */
504 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
505 /* go to next state */
506 card_set_state(ch, ISO_S_WAIT_TPDU);
507 return 0;
508 }
509
510 /* return number of bytes transmitted */
511 return 1;
512}
Harald Welte9d3e3822015-11-09 00:50:54 +0100513
514/**********************************************************************
515 * PTS / PPS handling
516 **********************************************************************/
517
Kévin Redon680bdab2018-07-18 14:00:57 +0200518/* Update the PTS sub-state */
Harald Welte9d3e3822015-11-09 00:50:54 +0100519static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss)
520{
Harald Weltedde112e2016-03-20 16:42:11 +0100521 TRACE_DEBUG("%u: 7816 PTS state %u -> %u\r\n",
522 ch->num, ch->pts.state, new_ptss);
Harald Welte9d3e3822015-11-09 00:50:54 +0100523 ch->pts.state = new_ptss;
524}
525
526/* Determine the next PTS state */
527static enum pts_state next_pts_state(struct card_handle *ch)
528{
529 uint8_t is_resp = ch->pts.state & 0x10;
530 uint8_t sstate = ch->pts.state & 0x0f;
531 uint8_t *pts_ptr;
532
533 if (!is_resp)
534 pts_ptr = ch->pts.req;
535 else
536 pts_ptr = ch->pts.resp;
537
538 switch (sstate) {
539 case PTS_S_WAIT_REQ_PTSS:
540 goto from_ptss;
541 case PTS_S_WAIT_REQ_PTS0:
542 goto from_pts0;
543 case PTS_S_WAIT_REQ_PTS1:
544 goto from_pts1;
545 case PTS_S_WAIT_REQ_PTS2:
546 goto from_pts2;
547 case PTS_S_WAIT_REQ_PTS3:
548 goto from_pts3;
549 }
550
551 if (ch->pts.state == PTS_S_WAIT_REQ_PCK)
552 return PTS_S_WAIT_RESP_PTSS;
553
554from_ptss:
555 return PTS_S_WAIT_REQ_PTS0 | is_resp;
556from_pts0:
557 if (pts_ptr[_PTS0] & (1 << 4))
558 return PTS_S_WAIT_REQ_PTS1 | is_resp;
559from_pts1:
560 if (pts_ptr[_PTS0] & (1 << 5))
561 return PTS_S_WAIT_REQ_PTS2 | is_resp;
562from_pts2:
563 if (pts_ptr[_PTS0] & (1 << 6))
564 return PTS_S_WAIT_REQ_PTS3 | is_resp;
565from_pts3:
566 return PTS_S_WAIT_REQ_PCK | is_resp;
567}
568
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200569/*! process incoming PTS byte
570 * @param[in] ch card handle on which the byte has been received
571 * @param[in] byte received PTS byte
572 * @return new iso7816_3_card_state or -1 at the end of PTS request
573 */
574static int process_byte_pts(struct card_handle *ch, uint8_t byte)
Harald Welte9d3e3822015-11-09 00:50:54 +0100575{
576 switch (ch->pts.state) {
577 case PTS_S_WAIT_REQ_PTSS:
578 ch->pts.req[_PTSS] = byte;
579 break;
580 case PTS_S_WAIT_REQ_PTS0:
581 ch->pts.req[_PTS0] = byte;
582 break;
583 case PTS_S_WAIT_REQ_PTS1:
584 ch->pts.req[_PTS1] = byte;
585 break;
586 case PTS_S_WAIT_REQ_PTS2:
587 ch->pts.req[_PTS2] = byte;
588 break;
589 case PTS_S_WAIT_REQ_PTS3:
590 ch->pts.req[_PTS3] = byte;
591 break;
592 case PTS_S_WAIT_REQ_PCK:
593 ch->pts.req[_PCK] = byte;
Harald Welte17db2f12016-02-26 09:48:57 +0100594 if (ch->pts.req[_PCK] != csum_pts(ch->pts.req)) {
Harald Weltedde112e2016-03-20 16:42:11 +0100595 TRACE_ERROR("%u: Error in PTS Checksum!\r\n",
596 ch->num);
Harald Welte17db2f12016-02-26 09:48:57 +0100597 /* Wait for the next TPDU */
598 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
599 return ISO_S_WAIT_TPDU;
600 }
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200601 /* FIXME check if proposal matches capabilities in TA1 */
Harald Welte9d3e3822015-11-09 00:50:54 +0100602 memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
603 break;
Harald Welte4c473da2015-11-14 13:31:11 +0100604 default:
Harald Weltedde112e2016-03-20 16:42:11 +0100605 TRACE_ERROR("%u: process_byte_pts() in invalid state %u\r\n",
606 ch->num, ch->pts.state);
Harald Welte4c473da2015-11-14 13:31:11 +0100607 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100608 }
609 /* calculate the next state and set it */
610 set_pts_state(ch, next_pts_state(ch));
611
Harald Welte4ba66d02016-02-25 19:38:56 +0100612 if (ch->pts.state == PTS_S_WAIT_RESP_PTSS) {
613 flush_pts(ch);
614 /* activate UART TX to transmit PTS response */
615 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
Harald Welte53079bb2016-03-20 14:58:35 +0100616 /* don't fall-through to the 'return ISO_S_IN_PTS'
617 * below, rather keep ISO7816 state as-is, it will be
618 * further updated by the tx-completion handler */
Harald Welteccb8a222016-03-20 13:37:11 +0100619 return -1;
Harald Welte4ba66d02016-02-25 19:38:56 +0100620 }
621
Harald Welte9d3e3822015-11-09 00:50:54 +0100622 return ISO_S_IN_PTS;
623}
624
625/* return a single byte to be transmitted to the reader */
Harald Welte855ba9e2016-02-24 21:00:46 +0100626static int tx_byte_pts(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100627{
Harald Welte855ba9e2016-02-24 21:00:46 +0100628 uint8_t byte;
629
630 /* 1: Determine the next transmit byte */
Harald Welte9d3e3822015-11-09 00:50:54 +0100631 switch (ch->pts.state) {
632 case PTS_S_WAIT_RESP_PTSS:
Harald Welte855ba9e2016-02-24 21:00:46 +0100633 byte = ch->pts.resp[_PTSS];
Harald Welte9d3e3822015-11-09 00:50:54 +0100634 break;
635 case PTS_S_WAIT_RESP_PTS0:
Harald Welte855ba9e2016-02-24 21:00:46 +0100636 byte = ch->pts.resp[_PTS0];
Harald Welte9d3e3822015-11-09 00:50:54 +0100637 break;
638 case PTS_S_WAIT_RESP_PTS1:
Harald Welte855ba9e2016-02-24 21:00:46 +0100639 byte = ch->pts.resp[_PTS1];
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200640 // TODO the value should have been validated when receiving the request
641 ch->f = iso7816_3_fi_table[byte >> 4]; // save selected Fn
642 if (0 == ch->f) {
643 TRACE_ERROR("%u: invalid F index in PPS response: %u\r\n", ch->num, byte >> 4);
644 // TODO become unresponsive to signal error condition
645 }
646 ch->d = iso7816_3_di_table[byte & 0xf]; // save selected Dn
647 if (0 == ch->d) {
648 TRACE_ERROR("%u: invalid D index in PPS response: %u\r\n", ch->num, byte & 0xf);
649 // TODO become unresponsive to signal error condition
650 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100651 break;
652 case PTS_S_WAIT_RESP_PTS2:
Harald Welte855ba9e2016-02-24 21:00:46 +0100653 byte = ch->pts.resp[_PTS2];
Harald Welte9d3e3822015-11-09 00:50:54 +0100654 break;
655 case PTS_S_WAIT_RESP_PTS3:
Harald Welte855ba9e2016-02-24 21:00:46 +0100656 byte = ch->pts.resp[_PTS3];
Harald Welte9d3e3822015-11-09 00:50:54 +0100657 break;
658 case PTS_S_WAIT_RESP_PCK:
Harald Welte855ba9e2016-02-24 21:00:46 +0100659 byte = ch->pts.resp[_PCK];
Harald Welte855ba9e2016-02-24 21:00:46 +0100660 break;
Harald Welted79dc4f2015-11-14 13:32:21 +0100661 default:
Harald Weltedde112e2016-03-20 16:42:11 +0100662 TRACE_ERROR("%u: get_byte_pts() in invalid state %u\r\n",
663 ch->num, ch->pts.state);
Harald Welte855ba9e2016-02-24 21:00:46 +0100664 return 0;
665 }
666
667 /* 2: Transmit the byte */
668 card_emu_uart_tx(ch->uart_chan, byte);
669
670 /* 3: Update the state */
671
672 switch (ch->pts.state) {
673 case PTS_S_WAIT_RESP_PCK:
Harald Weltec58bba02016-03-20 14:57:53 +0100674 card_emu_uart_wait_tx_idle(ch->uart_chan);
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200675 card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set selected baud rate
676 int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get new waiting time
677 if (wt <= 0) {
678 TRACE_ERROR("%u: invalid WT calculated: %ld\r\n", ch->num, wt);
679 // TODO become unresponsive to signal error condition
680 } else {
681 ch->wt = wt;
682 }
683 // FIXME disable WT
Harald Welte855ba9e2016-02-24 21:00:46 +0100684 /* Wait for the next TPDU */
685 card_set_state(ch, ISO_S_WAIT_TPDU);
686 set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
687 break;
688 default:
689 /* calculate the next state and set it */
690 set_pts_state(ch, next_pts_state(ch));
Harald Welted79dc4f2015-11-14 13:32:21 +0100691 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100692 }
Harald Welted79dc4f2015-11-14 13:32:21 +0100693
Harald Welte855ba9e2016-02-24 21:00:46 +0100694 /* return number of bytes transmitted */
695 return 1;
Harald Welte9d3e3822015-11-09 00:50:54 +0100696}
697
698
699/**********************************************************************
700 * TPDU handling
701 **********************************************************************/
702
Harald Welte4d804672015-11-14 23:02:38 +0100703
704/* compute number of data bytes according to Chapter 10.3.2 of 7816-3 */
705static unsigned int t0_num_data_bytes(uint8_t p3, int reader_to_card)
706{
707 if (reader_to_card) {
708 return p3;
709 } else {
710 if (p3 == 0)
711 return 256;
712 else
713 return p3;
714 }
715}
716
Harald Welte9d3e3822015-11-09 00:50:54 +0100717/* add a just-received TPDU byte (from reader) to USB buffer */
Harald Welte61bb30e2015-11-14 23:44:14 +0100718static void add_tpdu_byte(struct card_handle *ch, uint8_t byte)
Harald Welte9d3e3822015-11-09 00:50:54 +0100719{
Harald Welte8e7fca32017-05-07 16:14:33 +0200720 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100721 struct cardemu_usb_msg_rx_data *rd;
Harald Welte4d804672015-11-14 23:02:38 +0100722 unsigned int num_data_bytes = t0_num_data_bytes(ch->tpdu.hdr[_P3], 0);
Harald Welte9d3e3822015-11-09 00:50:54 +0100723
724 /* ensure we have a buffer */
Harald Welte8e7fca32017-05-07 16:14:33 +0200725 if (!ch->uart_rx_msg) {
Harald Welte25a9a802017-05-08 13:30:09 +0200726 msg = ch->uart_rx_msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
727 SIMTRACE_MSGT_DO_CEMU_RX_DATA);
Harald Welte8e7fca32017-05-07 16:14:33 +0200728 if (!ch->uart_rx_msg) {
Harald Weltedde112e2016-03-20 16:42:11 +0100729 TRACE_ERROR("%u: Received UART byte but ENOMEM\r\n",
730 ch->num);
Harald Welte9d3e3822015-11-09 00:50:54 +0100731 return;
Harald Welte4d804672015-11-14 23:02:38 +0100732 }
Harald Welte25a9a802017-05-08 13:30:09 +0200733 msgb_put(msg, sizeof(*rd));
Harald Welte9d3e3822015-11-09 00:50:54 +0100734 } else
Harald Welte8e7fca32017-05-07 16:14:33 +0200735 msg = ch->uart_rx_msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100736
Harald Welte25a9a802017-05-08 13:30:09 +0200737 rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
Harald Welte8e7fca32017-05-07 16:14:33 +0200738 msgb_put_u8(msg, byte);
Harald Welte9d3e3822015-11-09 00:50:54 +0100739
740 /* check if the buffer is full. If so, send it */
Harald Welte25a9a802017-05-08 13:30:09 +0200741 if (msgb_l2len(msg) >= sizeof(*rd) + num_data_bytes) {
Harald Welte4d804672015-11-14 23:02:38 +0100742 rd->flags |= CEMU_DATA_F_FINAL;
Harald Welteb5288e82015-11-14 21:15:52 +0100743 flush_rx_buffer(ch);
Harald Welte61bb30e2015-11-14 23:44:14 +0100744 /* We need to transmit the SW now, */
745 set_tpdu_state(ch, TPDU_S_WAIT_TX);
Harald Welte8e7fca32017-05-07 16:14:33 +0200746 } else if (msgb_tailroom(msg) <= 0)
Harald Welte4d804672015-11-14 23:02:38 +0100747 flush_rx_buffer(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100748}
749
750static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts)
751{
Harald Welte05b41c62015-11-14 20:58:48 +0100752 if (ch->tpdu.state == new_ts)
753 return;
Kévin Redon6b0afb32019-09-24 17:44:59 +0200754 if (ISO_S_IN_TPDU != ch->state && ISO_S_WAIT_TPDU != ch->state) {
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200755 TRACE_ERROR("%u: setting TPDU state in %s state\r\n", ch->num,
756 get_value_string(iso7816_3_card_state_names, ch->state));
757 }
Harald Welte05b41c62015-11-14 20:58:48 +0100758
Kévin Redon2fdcf3b2018-10-15 19:43:15 +0200759 TRACE_DEBUG("%u: 7816 TPDU state %s -> %s\r\n", ch->num,
760 get_value_string(tpdu_state_names, ch->tpdu.state),
761 get_value_string(tpdu_state_names, new_ts));
Harald Welte903d63a2016-03-20 13:38:39 +0100762 ch->tpdu.state = new_ts;
763
Harald Welte9d3e3822015-11-09 00:50:54 +0100764 switch (new_ts) {
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200765 case TPDU_S_WAIT_CLA: // we will be waiting for the next incoming TDPU
766 card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch back to receiving mode
767 card_emu_uart_update_wt(ch->uart_chan, 0); // disable waiting time since we don't expect any data
768 break;
769 case TPDU_S_WAIT_INS: // the reader started sending the TPDU header
770 card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest of the header/body
771 break;
772 case TPDU_S_WAIT_RX: // the reader should send us the TPDU body data
773 card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch to receive mode to receive the body
774 card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest body
Harald Welte9d3e3822015-11-09 00:50:54 +0100775 break;
776 case TPDU_S_WAIT_PB:
Kévin Redon76c2eeb2019-06-13 15:41:52 +0200777 card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // header is completely received, now we need to transmit the procedure byte
778 card_emu_uart_update_wt(ch->uart_chan, ch->wt); // prepare to extend the waiting time once half of it is reached
Harald Welte9d3e3822015-11-09 00:50:54 +0100779 break;
Harald Weltead434402016-03-02 11:18:29 +0100780 default:
781 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100782 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100783}
784
785static enum tpdu_state next_tpdu_state(struct card_handle *ch)
786{
787 switch (ch->tpdu.state) {
788 case TPDU_S_WAIT_CLA:
789 return TPDU_S_WAIT_INS;
790 case TPDU_S_WAIT_INS:
791 return TPDU_S_WAIT_P1;
792 case TPDU_S_WAIT_P1:
793 return TPDU_S_WAIT_P2;
794 case TPDU_S_WAIT_P2:
795 return TPDU_S_WAIT_P3;
796 case TPDU_S_WAIT_P3:
797 return TPDU_S_WAIT_PB;
798 /* simply stay in Rx or Tx by default */
799 case TPDU_S_WAIT_PB:
800 return TPDU_S_WAIT_PB;
801 case TPDU_S_WAIT_RX:
802 return TPDU_S_WAIT_RX;
803 case TPDU_S_WAIT_TX:
804 return TPDU_S_WAIT_TX;
805 }
Harald Welte4c473da2015-11-14 13:31:11 +0100806 /* we should never reach here */
807 assert(0);
808 return -1;
Harald Welte9d3e3822015-11-09 00:50:54 +0100809}
810
811static void send_tpdu_header(struct card_handle *ch)
812{
Harald Welte8e7fca32017-05-07 16:14:33 +0200813 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100814 struct cardemu_usb_msg_rx_data *rd;
Harald Welte8e7fca32017-05-07 16:14:33 +0200815 uint8_t *cur;
Harald Welte9d3e3822015-11-09 00:50:54 +0100816
Harald Weltedde112e2016-03-20 16:42:11 +0100817 TRACE_INFO("%u: %s: %02x %02x %02x %02x %02x\r\n",
818 ch->num, __func__,
Harald Welte43f79492016-02-29 10:06:54 +0100819 ch->tpdu.hdr[0], ch->tpdu.hdr[1],
820 ch->tpdu.hdr[2], ch->tpdu.hdr[3],
821 ch->tpdu.hdr[4]);
822
Harald Welte9d3e3822015-11-09 00:50:54 +0100823 /* if we already/still have a context, send it off */
Harald Welte8e7fca32017-05-07 16:14:33 +0200824 if (ch->uart_rx_msg) {
Harald Weltedde112e2016-03-20 16:42:11 +0100825 TRACE_DEBUG("%u: have old buffer\r\n", ch->num);
Harald Welte8e7fca32017-05-07 16:14:33 +0200826 if (msgb_l2len(ch->uart_rx_msg)) {
Harald Weltedde112e2016-03-20 16:42:11 +0100827 TRACE_DEBUG("%u: flushing old buffer\r\n", ch->num);
Harald Weltef1697e22016-03-02 10:28:54 +0100828 flush_rx_buffer(ch);
829 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100830 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200831 TRACE_DEBUG("%u: allocating new buffer\r\n", ch->num);
832 /* ensure we have a new buffer */
Harald Welte25a9a802017-05-08 13:30:09 +0200833 ch->uart_rx_msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
834 SIMTRACE_MSGT_DO_CEMU_RX_DATA);
Harald Welte8e7fca32017-05-07 16:14:33 +0200835 if (!ch->uart_rx_msg) {
836 TRACE_ERROR("%u: %s: ENOMEM\r\n", ch->num, __func__);
837 return;
838 }
839 msg = ch->uart_rx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200840 rd = (struct cardemu_usb_msg_rx_data *) msgb_put(msg, sizeof(*rd));
Harald Welte9d3e3822015-11-09 00:50:54 +0100841
Harald Welte8e7fca32017-05-07 16:14:33 +0200842 /* initialize header */
Harald Welte9d3e3822015-11-09 00:50:54 +0100843 rd->flags = CEMU_DATA_F_TPDU_HDR;
Harald Welte9d3e3822015-11-09 00:50:54 +0100844
845 /* copy TPDU header to data field */
Harald Welte8e7fca32017-05-07 16:14:33 +0200846 cur = msgb_put(msg, sizeof(ch->tpdu.hdr));
847 memcpy(cur, ch->tpdu.hdr, sizeof(ch->tpdu.hdr));
Harald Welteb5288e82015-11-14 21:15:52 +0100848 /* rd->data_len is set in flush_rx_buffer() */
Harald Welte9d3e3822015-11-09 00:50:54 +0100849
Harald Welteb5288e82015-11-14 21:15:52 +0100850 flush_rx_buffer(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +0100851}
852
853static enum iso7816_3_card_state
854process_byte_tpdu(struct card_handle *ch, uint8_t byte)
855{
856 switch (ch->tpdu.state) {
857 case TPDU_S_WAIT_CLA:
858 ch->tpdu.hdr[_CLA] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100859 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100860 break;
861 case TPDU_S_WAIT_INS:
862 ch->tpdu.hdr[_INS] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100863 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100864 break;
865 case TPDU_S_WAIT_P1:
866 ch->tpdu.hdr[_P1] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100867 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100868 break;
869 case TPDU_S_WAIT_P2:
870 ch->tpdu.hdr[_P2] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100871 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100872 break;
873 case TPDU_S_WAIT_P3:
874 ch->tpdu.hdr[_P3] = byte;
Harald Welte4d804672015-11-14 23:02:38 +0100875 set_tpdu_state(ch, next_tpdu_state(ch));
Harald Welte9d3e3822015-11-09 00:50:54 +0100876 /* FIXME: start timer to transmit further 0x60 */
877 /* send the TPDU header as part of a procedure byte
878 * request to the USB host */
879 send_tpdu_header(ch);
880 break;
881 case TPDU_S_WAIT_RX:
Harald Welte61bb30e2015-11-14 23:44:14 +0100882 add_tpdu_byte(ch, byte);
883 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100884 default:
Harald Weltedde112e2016-03-20 16:42:11 +0100885 TRACE_ERROR("%u: process_byte_tpdu() in invalid state %u\r\n",
886 ch->num, ch->tpdu.state);
Harald Welte9d3e3822015-11-09 00:50:54 +0100887 }
Harald Welte9d3e3822015-11-09 00:50:54 +0100888
889 /* ensure we stay in TPDU ISO state */
890 return ISO_S_IN_TPDU;
891}
892
Harald Welte855ba9e2016-02-24 21:00:46 +0100893/* tx a single byte to be transmitted to the reader */
894static int tx_byte_tpdu(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100895{
Harald Welte8e7fca32017-05-07 16:14:33 +0200896 struct msgb *msg;
Harald Welte9d3e3822015-11-09 00:50:54 +0100897 struct cardemu_usb_msg_tx_data *td;
Harald Welte855ba9e2016-02-24 21:00:46 +0100898 uint8_t byte;
Harald Welte9d3e3822015-11-09 00:50:54 +0100899
900 /* ensure we are aware of any data that might be pending for
901 * transmit */
Harald Welte8e7fca32017-05-07 16:14:33 +0200902 if (!ch->uart_tx_msg) {
Harald Welte53079bb2016-03-20 14:58:35 +0100903 /* uart_tx_queue is filled from main loop, so no need
904 * for irq-safe operations */
Harald Welte54cb3d02016-02-29 14:12:40 +0100905 if (llist_empty(&ch->uart_tx_queue))
Harald Welte9d3e3822015-11-09 00:50:54 +0100906 return 0;
907
Harald Welte54cb3d02016-02-29 14:12:40 +0100908 /* dequeue first at head */
Harald Welte8e7fca32017-05-07 16:14:33 +0200909 ch->uart_tx_msg = msgb_dequeue(&ch->uart_tx_queue);
Harald Welte25a9a802017-05-08 13:30:09 +0200910 ch->uart_tx_msg->l1h = ch->uart_tx_msg->head;
911 ch->uart_tx_msg->l2h = ch->uart_tx_msg->l1h + sizeof(struct simtrace_msg_hdr);
Harald Welte8e7fca32017-05-07 16:14:33 +0200912 msg = ch->uart_tx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200913 /* remove the header */
914 msgb_pull(msg, sizeof(struct simtrace_msg_hdr) + sizeof(*td));
Harald Welte9d3e3822015-11-09 00:50:54 +0100915 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200916 msg = ch->uart_tx_msg;
Harald Welte25a9a802017-05-08 13:30:09 +0200917 td = (struct cardemu_usb_msg_tx_data *) msg->l2h;
Harald Welte9d3e3822015-11-09 00:50:54 +0100918
Harald Welte8e7fca32017-05-07 16:14:33 +0200919 /* take the next pending byte out of the msgb */
920 byte = msgb_pull_u8(msg);
Harald Welte855ba9e2016-02-24 21:00:46 +0100921
922 card_emu_uart_tx(ch->uart_chan, byte);
Harald Welte9d3e3822015-11-09 00:50:54 +0100923
Kévin Redon0f4abf52018-08-02 17:42:48 +0200924 /* this must happen _after_ the byte has been transmitted */
Harald Weltef16b6182016-02-24 22:18:46 +0100925 switch (ch->tpdu.state) {
926 case TPDU_S_WAIT_PB:
927 /* if we just transmitted the procedure byte, we need to decide
928 * if we want to continue to receive or transmit */
929 if (td->flags & CEMU_DATA_F_PB_AND_TX)
930 set_tpdu_state(ch, TPDU_S_WAIT_TX);
931 else if (td->flags & CEMU_DATA_F_PB_AND_RX)
932 set_tpdu_state(ch, TPDU_S_WAIT_RX);
933 break;
Harald Weltead434402016-03-02 11:18:29 +0100934 default:
935 break;
Harald Weltef16b6182016-02-24 22:18:46 +0100936 }
937
Harald Welte9d3e3822015-11-09 00:50:54 +0100938 /* check if the buffer has now been fully transmitted */
Harald Welte8e7fca32017-05-07 16:14:33 +0200939 if (msgb_length(msg) == 0) {
Harald Welte52922ff2015-11-14 20:59:56 +0100940 if (td->flags & CEMU_DATA_F_PB_AND_RX) {
941 /* we have just sent the procedure byte and now
942 * need to continue receiving */
943 set_tpdu_state(ch, TPDU_S_WAIT_RX);
Harald Welte2935b3c2015-11-14 20:00:14 +0100944 } else {
Harald Welte52922ff2015-11-14 20:59:56 +0100945 /* we have transmitted all bytes */
946 if (td->flags & CEMU_DATA_F_FINAL) {
947 /* this was the final part of the APDU, go
Harald Welte53079bb2016-03-20 14:58:35 +0100948 * back to state one */
Harald Welte52922ff2015-11-14 20:59:56 +0100949 card_set_state(ch, ISO_S_WAIT_TPDU);
Harald Welte52922ff2015-11-14 20:59:56 +0100950 }
Harald Welte2935b3c2015-11-14 20:00:14 +0100951 }
Harald Welte8e7fca32017-05-07 16:14:33 +0200952 usb_buf_free(msg);
953 ch->uart_tx_msg = NULL;
Harald Welte9d3e3822015-11-09 00:50:54 +0100954 }
955
956 return 1;
957}
958
959/**********************************************************************
960 * Public API
961 **********************************************************************/
962
963/* process a single byte received from the reader */
964void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
965{
966 int new_state = -1;
967
968 ch->stats.rx_bytes++;
969
970 switch (ch->state) {
Harald Welte9d3e3822015-11-09 00:50:54 +0100971 case ISO_S_WAIT_TPDU:
972 if (byte == 0xff) {
973 new_state = process_byte_pts(ch, byte);
974 ch->stats.pps++;
975 goto out_silent;
976 }
977 /* fall-through */
978 case ISO_S_IN_TPDU:
979 new_state = process_byte_tpdu(ch, byte);
980 break;
981 case ISO_S_IN_PTS:
982 new_state = process_byte_pts(ch, byte);
983 goto out_silent;
Kévin Redon5f6b8712018-07-11 09:49:06 +0200984 default:
985 TRACE_ERROR("%u: Received UART char in invalid 7816 state "
986 "%u\r\n", ch->num, ch->state);
987 break;
Harald Welte9d3e3822015-11-09 00:50:54 +0100988 }
989
990out_silent:
991 if (new_state != -1)
992 card_set_state(ch, new_state);
993}
994
Harald Welte855ba9e2016-02-24 21:00:46 +0100995/* transmit a single byte to the reader */
996int card_emu_tx_byte(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +0100997{
998 int rc = 0;
999
1000 switch (ch->state) {
1001 case ISO_S_IN_ATR:
Kévin Redonebe672e2018-07-29 00:18:12 +02001002 rc = tx_byte_atr(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +01001003 break;
1004 case ISO_S_IN_PTS:
Harald Welte855ba9e2016-02-24 21:00:46 +01001005 rc = tx_byte_pts(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +01001006 break;
1007 case ISO_S_IN_TPDU:
Harald Welte855ba9e2016-02-24 21:00:46 +01001008 rc = tx_byte_tpdu(ch);
Harald Welte9d3e3822015-11-09 00:50:54 +01001009 break;
Harald Weltead434402016-03-02 11:18:29 +01001010 default:
1011 break;
Harald Welte9d3e3822015-11-09 00:50:54 +01001012 }
1013
1014 if (rc)
1015 ch->stats.tx_bytes++;
1016
Harald Welte4d804672015-11-14 23:02:38 +01001017 /* if we return 0 here, the UART needs to disable transmit-ready
1018 * interrupts */
Harald Welte9d3e3822015-11-09 00:50:54 +01001019 return rc;
1020}
1021
Harald Welteacae4122016-03-02 10:27:58 +01001022void card_emu_have_new_uart_tx(struct card_handle *ch)
1023{
1024 switch (ch->state) {
1025 case ISO_S_IN_TPDU:
1026 switch (ch->tpdu.state) {
1027 case TPDU_S_WAIT_TX:
1028 case TPDU_S_WAIT_PB:
1029 card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
1030 break;
1031 default:
1032 break;
1033 }
1034 default:
1035 break;
1036 }
1037}
1038
Harald Welteff160652016-03-19 21:59:06 +01001039void card_emu_report_status(struct card_handle *ch)
1040{
Harald Welte8e7fca32017-05-07 16:14:33 +02001041 struct msgb *msg;
Harald Welteff160652016-03-19 21:59:06 +01001042 struct cardemu_usb_msg_status *sts;
1043
Harald Welte25a9a802017-05-08 13:30:09 +02001044 msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
1045 SIMTRACE_MSGT_BD_CEMU_STATUS);
Harald Welte8e7fca32017-05-07 16:14:33 +02001046 if (!msg)
Harald Welteff160652016-03-19 21:59:06 +01001047 return;
Harald Welte8e7fca32017-05-07 16:14:33 +02001048
Harald Welte25a9a802017-05-08 13:30:09 +02001049 sts = (struct cardemu_usb_msg_status *) msgb_put(msg, sizeof(*sts));
Harald Welteff160652016-03-19 21:59:06 +01001050 sts->flags = 0;
1051 if (ch->vcc_active)
1052 sts->flags |= CEMU_STATUS_F_VCC_PRESENT;
1053 if (ch->clocked)
1054 sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;
1055 if (ch->in_reset)
1056 sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001057 /* FIXME set voltage and card insert values */
1058 sts->f = ch->f;
1059 sts->d = ch->d;
Harald Welteff160652016-03-19 21:59:06 +01001060 sts->wi = ch->wi;
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001061 sts->wt = ch->wt;
Harald Welteff160652016-03-19 21:59:06 +01001062
Harald Welte25a9a802017-05-08 13:30:09 +02001063 usb_buf_upd_len_and_submit(msg);
Harald Welteff160652016-03-19 21:59:06 +01001064}
1065
Harald Welte9d3e3822015-11-09 00:50:54 +01001066/* hardware driver informs us that a card I/O signal has changed */
1067void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
1068{
1069 switch (io) {
1070 case CARD_IO_VCC:
Harald Welte47ee2832016-02-29 10:09:46 +01001071 if (active == 0 && ch->vcc_active == 1) {
Harald Weltedde112e2016-03-20 16:42:11 +01001072 TRACE_INFO("%u: VCC deactivated\r\n", ch->num);
Harald Welte9d3e3822015-11-09 00:50:54 +01001073 card_set_state(ch, ISO_S_WAIT_POWER);
Harald Welte47ee2832016-02-29 10:09:46 +01001074 } else if (active == 1 && ch->vcc_active == 0) {
Harald Weltedde112e2016-03-20 16:42:11 +01001075 TRACE_INFO("%u: VCC activated\r\n", ch->num);
Harald Welte9d3e3822015-11-09 00:50:54 +01001076 card_set_state(ch, ISO_S_WAIT_CLK);
Harald Welte47ee2832016-02-29 10:09:46 +01001077 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001078 ch->vcc_active = active;
1079 break;
1080 case CARD_IO_CLK:
Harald Welte47ee2832016-02-29 10:09:46 +01001081 if (active == 1 && ch->clocked == 0) {
Harald Weltedde112e2016-03-20 16:42:11 +01001082 TRACE_INFO("%u: CLK activated\r\n", ch->num);
Harald Welte47ee2832016-02-29 10:09:46 +01001083 if (ch->state == ISO_S_WAIT_CLK)
1084 card_set_state(ch, ISO_S_WAIT_RST);
1085 } else if (active == 0 && ch->clocked == 1) {
Harald Weltedde112e2016-03-20 16:42:11 +01001086 TRACE_INFO("%u: CLK deactivated\r\n", ch->num);
Harald Welte47ee2832016-02-29 10:09:46 +01001087 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001088 ch->clocked = active;
1089 break;
1090 case CARD_IO_RST:
Harald Welte47ee2832016-02-29 10:09:46 +01001091 if (active == 0 && ch->in_reset) {
Harald Weltedde112e2016-03-20 16:42:11 +01001092 TRACE_INFO("%u: RST released\r\n", ch->num);
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001093 if (ch->vcc_active && ch->clocked && ISO_S_WAIT_RST == ch->state) {
Kévin Redonebe672e2018-07-29 00:18:12 +02001094 /* prepare to send the ATR */
Harald Welte47ee2832016-02-29 10:09:46 +01001095 card_set_state(ch, ISO_S_WAIT_ATR);
Harald Welte47ee2832016-02-29 10:09:46 +01001096 }
1097 } else if (active && !ch->in_reset) {
Harald Weltedde112e2016-03-20 16:42:11 +01001098 TRACE_INFO("%u: RST asserted\r\n", ch->num);
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001099 card_set_state(ch, ISO_S_WAIT_RST);
Harald Welte9d3e3822015-11-09 00:50:54 +01001100 }
1101 ch->in_reset = active;
1102 break;
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001103 default:
1104 break;
Harald Welte9d3e3822015-11-09 00:50:54 +01001105 }
1106}
1107
1108/* User sets a new ATR to be returned during next card reset */
1109int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
1110{
1111 if (len > sizeof(ch->atr.atr))
1112 return -1;
1113
Kévin Redonb149ea32019-09-24 17:48:25 +02001114/* ignore new ATR for now since we PPS has not been tested
Harald Welte9d3e3822015-11-09 00:50:54 +01001115 memcpy(ch->atr.atr, atr, len);
1116 ch->atr.len = len;
1117 ch->atr.idx = 0;
Kévin Redonb149ea32019-09-24 17:48:25 +02001118*/
Harald Welte9d3e3822015-11-09 00:50:54 +01001119
Kévin Redonebe672e2018-07-29 00:18:12 +02001120#if TRACE_LEVEL >= TRACE_LEVEL_INFO
1121 uint8_t i;
1122 TRACE_INFO("%u: ATR set: ", ch->num);
Kévin Redonb149ea32019-09-24 17:48:25 +02001123 for (i = 0; i < len; i++) {
Kévin Redonebe672e2018-07-29 00:18:12 +02001124 TRACE_INFO_WP("%02x ", atr[i]);
1125 }
1126 TRACE_INFO_WP("\n\r");
Kévin Redonb149ea32019-09-24 17:48:25 +02001127 TRACE_INFO("%u: ATR set currently ignored\n\r", ch->num);
Kévin Redonebe672e2018-07-29 00:18:12 +02001128#endif
1129 /* FIXME: race condition with transmitting ATR to reader? */
Harald Welte9d3e3822015-11-09 00:50:54 +01001130
1131 return 0;
1132}
1133
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001134void card_emu_wt_halfed(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +01001135{
Harald Weltedda73552016-03-02 10:29:55 +01001136 switch (ch->state) {
1137 case ISO_S_IN_TPDU:
1138 switch (ch->tpdu.state) {
Harald Weltedda73552016-03-02 10:29:55 +01001139 case TPDU_S_WAIT_TX:
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001140 case TPDU_S_WAIT_PB:
Harald Weltedda73552016-03-02 10:29:55 +01001141 putchar('N');
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001142 card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL); // we are waiting for data from the user. send a procedure byte to ask the reader to wait more time
1143 card_emu_uart_reset_wt(ch->uart_chan); // reset WT
Harald Weltedda73552016-03-02 10:29:55 +01001144 break;
1145 default:
1146 break;
1147 }
Harald Weltedda73552016-03-02 10:29:55 +01001148 default:
1149 break;
1150 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001151}
1152
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001153void card_emu_wt_expired(struct card_handle *ch)
Harald Welte9d3e3822015-11-09 00:50:54 +01001154{
Kévin Redonebe672e2018-07-29 00:18:12 +02001155 switch (ch->state) {
1156 case ISO_S_WAIT_ATR:
1157 /* ISO 7816-3 6.2.1 time tc has passed, we can now send the ATR */
1158 card_set_state(ch, ISO_S_IN_ATR);
1159 break;
1160 default:
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001161 // TODO become unresponsive
Kévin Redonebe672e2018-07-29 00:18:12 +02001162 TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
1163 break;
1164 }
Harald Welte9d3e3822015-11-09 00:50:54 +01001165}
1166
Kévin Redon1a88fd82019-05-15 00:23:21 +02001167/* shortest ATR possible (uses default speed and no options) */
1168static const uint8_t default_atr[] = { 0x3B, 0x00 };
Harald Welte9d3e3822015-11-09 00:50:54 +01001169
1170static struct card_handle card_handles[NUM_SLOTS];
1171
Harald Welte8e7fca32017-05-07 16:14:33 +02001172struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan,
1173 uint8_t in_ep, uint8_t irq_ep)
Harald Welte9d3e3822015-11-09 00:50:54 +01001174{
1175 struct card_handle *ch;
1176
1177 if (slot_num >= ARRAY_SIZE(card_handles))
1178 return NULL;
1179
1180 ch = &card_handles[slot_num];
1181
1182 memset(ch, 0, sizeof(*ch));
1183
Harald Welte54cb3d02016-02-29 14:12:40 +01001184 INIT_LLIST_HEAD(&ch->uart_tx_queue);
1185
Kévin Redon680bdab2018-07-18 14:00:57 +02001186 /* initialize the card_handle with reasonable defaults */
Harald Weltedde112e2016-03-20 16:42:11 +01001187 ch->num = slot_num;
Harald Welte8e7fca32017-05-07 16:14:33 +02001188 ch->irq_ep = irq_ep;
1189 ch->in_ep = in_ep;
Harald Welte9d3e3822015-11-09 00:50:54 +01001190 ch->state = ISO_S_WAIT_POWER;
1191 ch->vcc_active = 0;
1192 ch->in_reset = 1;
1193 ch->clocked = 0;
1194
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001195 ch->fi = ISO7816_3_DEFAULT_FI;
1196 ch->di = ISO7816_3_DEFAULT_DI;
Harald Welte9d3e3822015-11-09 00:50:54 +01001197 ch->wi = ISO7816_3_DEFAULT_WI;
Kévin Redon76c2eeb2019-06-13 15:41:52 +02001198 ch->wt = ISO7816_3_DEFAULT_WT;;
Harald Welte9d3e3822015-11-09 00:50:54 +01001199
1200 ch->tc_chan = tc_chan;
1201 ch->uart_chan = uart_chan;
Harald Welte9d3e3822015-11-09 00:50:54 +01001202
1203 ch->atr.idx = 0;
1204 ch->atr.len = sizeof(default_atr);
1205 memcpy(ch->atr.atr, default_atr, ch->atr.len);
1206
1207 ch->pts.state = PTS_S_WAIT_REQ_PTSS;
1208 ch->tpdu.state = TPDU_S_WAIT_CLA;
1209
Harald Welte9d3e3822015-11-09 00:50:54 +01001210 return ch;
1211}