blob: f20cbcd030caa4336bdc6818b5850cb894d20c2b [file] [log] [blame]
Harald Welte06348362019-05-19 00:45:17 +02001/* ISO 7816-3 Finite State Machine (reader side)
2 *
3 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
4 *
5 * inspired by earlier work
6 * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
7 * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22 */
23
24#include <string.h>
25
26#include <osmocom/core/utils.h>
27#include <osmocom/core/msgb.h>
28#include <osmocom/core/fsm.h>
29#include <osmocom/core/logging.h>
30#include <osmocom/sim/sim.h>
31
32#include "logging.h"
33#include "cuart.h"
34#include "iso7816_fsm.h"
35
36/* Section 8.2: the Answer-to-Reset (... a string of at most 32 bytes) */
37#define MAX_ATR_SIZE 32
38
39#define S(x) (1 << (x))
40
41/*! ISO 7816-3 states */
42enum iso7816_3_state {
43 ISO7816_S_RESET, /*!< in Reset */
44 ISO7816_S_WAIT_ATR, /*!< waiting for ATR to start */
45 ISO7816_S_IN_ATR, /*!< while we are receiving the ATR */
46 ISO7816_S_WAIT_TPDU, /*!< waiting for start of new TPDU */
47 ISO7816_S_IN_TPDU, /*!< inside a single TPDU */
48 ISO7816_S_IN_PPS_REQ, /*!< while we are inside the PPS request */
49 ISO7816_S_WAIT_PPS_RSP, /*!< waiting for start of the PPS response */
50 ISO7816_S_IN_PPS_RSP, /*!< while we are inside the PPS request */
51};
52
53/*! Answer-To-Reset (ATR) sub-states of ISO7816_S_IN_ATR
54 * @note defined in ISO/IEC 7816-3:2006(E) section 8
55 */
56enum atr_state {
57 ATR_S_WAIT_TS, /*!< initial byte */
58 ATR_S_WAIT_T0, /*!< format byte */
59 ATR_S_WAIT_TA, /*!< first sub-group interface byte */
60 ATR_S_WAIT_TB, /*!< second sub-group interface byte */
61 ATR_S_WAIT_TC, /*!< third sub-group interface byte */
62 ATR_S_WAIT_TD, /*!< fourth sub-group interface byte */
63 ATR_S_WAIT_HIST, /*!< historical byte */
64 ATR_S_WAIT_TCK, /*!< check byte */
65 ATR_S_DONE
66};
67
68/*! Protocol and Parameters Selection (PPS) sub-states of ISO7816_S_IN_PTS_REQ/ISO7816_S_IN_PTS_RSP
69 * @note defined in ISO/IEC 7816-3:2006(E) section 9
70 */
71enum pps_state {
72 PPS_S_WAIT_PPSS, /*!< initial byte */
73 PPS_S_WAIT_PPS0, /*!< format byte */
74 PPS_S_WAIT_PPS1, /*!< first parameter byte */
75 PPS_S_WAIT_PPS2, /*!< second parameter byte */
76 PPS_S_WAIT_PPS3, /*!< third parameter byte */
77 PPS_S_WAIT_PCK, /*!< check byte */
78 PPS_S_WAIT_END, /*!< all done */
79 PPS_S_DONE
80};
81
82/*! Transport Protocol Data Unit (TPDU) sub-states of ISO7816_S_IN_TPDU
83 * @note defined in ISO/IEC 7816-3:2006(E) section 10 and 12
84 * @remark APDUs are formed by one or more command+response TPDUs
85 */
86enum tpdu_state {
87 TPDU_S_INIT, /*!< initial state */
88 TPDU_S_TX_HDR, /*!< transmitting hdr, waiting for completion */
89 TPDU_S_PROCEDURE, /*!< procedure byte (could also be SW1) */
90 TPDU_S_TX_REMAINING, /*!< Tx remaining data bytes */
91 TPDU_S_TX_SINGLE, /*!< Tx single data byte */
92 TPDU_S_RX_REMAINING, /*!< Rx remaining data bytes */
93 TPDU_S_RX_SINGLE, /*!< Rx single data byte */
94 TPDU_S_SW1, /*!< first status word */
95 TPDU_S_SW2, /*!< second status word */
96 TPDU_S_DONE,
97};
98
99/* FSM timer enumeration */
100enum iso7816_3_timer {
101 T_WAIT_ATR = 1,
102 T_GUARD,
103};
104
105/* forward declarations */
106static struct osmo_fsm iso7816_3_fsm;
107static struct osmo_fsm atr_fsm;
108static struct osmo_fsm tpdu_fsm;
109static struct osmo_fsm pps_fsm;
110
111/* look-up table for bit-wise inversion to convert from "inverse convention" to normal */
112static const uint8_t convention_convert_lut[256] = {
113 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f,
114 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07,
115 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b,
116 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03,
117 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d,
118 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05,
119 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09,
120 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01,
121 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
122 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06,
123 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a,
124 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02,
125 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c,
126 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04,
127 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08,
128 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00,
129};
130
131/***********************************************************************
132 * ISO7816-3 Main FSM
133 ***********************************************************************/
134
135static const struct value_string iso7816_3_event_names[] = {
136 { ISO7816_E_RX_SINGLE, "UART_RX_SINGLE" },
137 { ISO7816_E_RX_COMPL, "UART_RX_COMPL" },
138 { ISO7816_E_TX_COMPL, "UART_TX_COMPL" },
139 { ISO7816_E_POWER_UP_IND, "POWER_UP_IND" },
140 { ISO7816_E_RESET_REL_IND, "RESET_REL_IND" },
141 { ISO7816_E_RX_ERR_IND, "RX_ERR_IND" },
142 { ISO7816_E_TX_ERR_IND, "TX_ERR_IND" },
143 { ISO7816_E_ATR_DONE_IND, "ATR_DONE_IND" },
144 { ISO7816_E_TPDU_DONE_IND, "TPDU_DONE_IND" },
145 { ISO7816_E_XCEIVE_TPDU_CMD, "XCEIVE_TPDU_CMD" },
146 /* allstate events */
147 { ISO7816_E_WTIME_EXP, "WAIT_TIME_EXP" },
148 { ISO7816_E_HW_ERR_IND, "HW_ERR_IND" },
149 { ISO7816_E_SW_ERR_IND, "SW_ERR_IND" },
150 { ISO7816_E_CARD_REMOVAL, "CARD_REMOVAL" },
151 { ISO7816_E_POWER_DN_IND, "POWER_DN_IND" },
152 { ISO7816_E_RESET_ACT_IND, "RESET_ACT_IND" },
153 { ISO7816_E_ABORT_REQ, "ABORT_REQ" },
154 { ISO7816_E_TPDU_CLEAR_REQ, "TPDU_CLEAR_REQ" },
155 { 0, NULL }
156};
157
158struct iso7816_3_priv {
159 uint8_t slot_nr;
160 /* child FSM instances */
161 struct osmo_fsm_inst *atr_fi;
162 struct osmo_fsm_inst *pps_fi;
163 struct osmo_fsm_inst *tpdu_fi;
164 /* other data */
165 bool convention_convert;/*!< If convention conversion is needed */
166 uint16_t guard_time_ms;
167 /* underlying UART */
168 struct card_uart *uart;
169 iso7816_user_cb user_cb;
170 void *user_priv;
171};
172
173/* type-safe method to obtain iso7816_3_priv from fi */
174static struct iso7816_3_priv *get_iso7816_3_priv(struct osmo_fsm_inst *fi)
175{
176 OSMO_ASSERT(fi);
177 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
178 return (struct iso7816_3_priv *) fi->priv;
179}
180
181/* convert from clock cycles of the CLK line to milli-seconds */
182uint32_t fi_cycles2ms(struct osmo_fsm_inst *fi, uint32_t cyclces)
183{
184 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
185 /* FIXME */
186 return 1000;
187}
188
189/* card UART notifies us: dispatch to (main ISO7816-3) FSM */
190static void tpdu_uart_notification(struct card_uart *cuart, enum card_uart_event evt, void *data)
191{
192 struct osmo_fsm_inst *fi = (struct osmo_fsm_inst *) cuart->priv;
193 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
194
195 LOGPFSML(fi, LOGL_DEBUG, "UART Notification '%s'\n",
196 get_value_string(card_uart_event_vals, evt));
197
198 /* FIXME: Set only flags here; Main loop polls flags and dispatches events */
199
200 switch (evt) {
201 case CUART_E_RX_SINGLE:
202 osmo_fsm_inst_dispatch(fi, ISO7816_E_RX_SINGLE, data);
203 break;
204 case CUART_E_RX_COMPLETE:
205 osmo_fsm_inst_dispatch(fi, ISO7816_E_RX_COMPL, data);
206 break;
207 case CUART_E_RX_TIMEOUT:
208 osmo_fsm_inst_dispatch(fi, ISO7816_E_WTIME_EXP, data);
209 break;
210 case CUART_E_TX_COMPLETE:
211 osmo_fsm_inst_dispatch(fi, ISO7816_E_TX_COMPL, data);
212 break;
213 }
214}
215
216static void iso7816_3_reset_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
217{
218 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
219 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
220
221 /* go back to initial state in child FSMs */
222 osmo_fsm_inst_state_chg(ip->atr_fi, ATR_S_WAIT_TS, 0, 0);
223 //osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_WAIT_PPSS, 0, 0);
224 osmo_fsm_inst_state_chg(ip->tpdu_fi, TPDU_S_INIT, 0, 0);
225}
226
227static void iso7816_3_reset_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
228{
229 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
230 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
231
232 switch (event) {
233 case ISO7816_E_RESET_REL_IND:
234 /* TOOD: this should happen before reset is released */
235 card_uart_ctrl(ip->uart, CUART_CTL_RX, true);
236 osmo_fsm_inst_state_chg_ms(fi, ISO7816_S_WAIT_ATR,
237 fi_cycles2ms(fi, 40000), T_WAIT_ATR);
238 break;
239 default:
240 OSMO_ASSERT(0);
241 }
242}
243
244static void iso7816_3_wait_atr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
245{
246 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
247 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
248
249 switch (event) {
250 case ISO7816_E_RX_SINGLE:
251 osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_ATR, 0, 0);
252 osmo_fsm_inst_dispatch(ip->atr_fi, event, data);
253 break;
254 default:
255 OSMO_ASSERT(0);
256 }
257}
258
259static void iso7816_3_in_atr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
260{
261 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
262 struct msgb *atr;
263 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
264
265 switch (event) {
266 case ISO7816_E_RX_SINGLE:
267 case ISO7816_E_RX_ERR_IND:
268 /* simply pass this through to the child FSM for the ATR */
269 osmo_fsm_inst_dispatch(ip->atr_fi, event, data);
270 break;
271 case ISO7816_E_ATR_DONE_IND:
272 atr = data;
273 /* FIXME: verify ATR result: success / failure */
274 osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);
275 /* notify user about ATR */
276 ip->user_cb(fi, event, 0, atr);
277 break;
278 default:
279 OSMO_ASSERT(0);
280 }
281}
282
283static void iso7816_3_wait_tpdu_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
284{
285 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
286 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
287 /* reset the TPDU state machine */
288 osmo_fsm_inst_dispatch(ip->tpdu_fi, ISO7816_E_TPDU_CLEAR_REQ, NULL);
289}
290
291static void iso7816_3_wait_tpdu_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
292{
293 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
294 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
295
296 switch (event) {
297 case ISO7816_E_XCEIVE_TPDU_CMD:
298 /* "data" contains a msgb-wrapped TPDU */
299 osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_TPDU, 0, 0);
300 /* pass on to sub-fsm */
301 osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data);
302 break;
303 default:
304 OSMO_ASSERT(0);
305 }
306}
307
308static void iso7816_3_in_tpdu_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
309{
310 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
311 struct msgb *apdu;
312 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
313
314 switch (event) {
315 case ISO7816_E_RX_SINGLE:
316 case ISO7816_E_RX_COMPL:
317 case ISO7816_E_RX_ERR_IND:
318 case ISO7816_E_TX_COMPL:
319 case ISO7816_E_TX_ERR_IND:
320 /* simply pass this through to the child FSM for the ATR */
321 osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data);
322 break;
323 case ISO7816_E_TPDU_DONE_IND:
324 apdu = data;
325 osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);
326 /* hand finished TPDU to user */
327 ip->user_cb(fi, event, 0, apdu);
328 break;
329 default:
330 OSMO_ASSERT(0);
331 }
332}
333
334static void iso7816_3_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
335{
336 OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
337
338 switch (event) {
339 case ISO7816_E_WTIME_EXP:
340 case ISO7816_E_HW_ERR_IND:
341 case ISO7816_E_CARD_REMOVAL:
342 /* FIXME: power off? */
343 osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);
344 break;
345 case ISO7816_E_POWER_DN_IND:
346 case ISO7816_E_RESET_ACT_IND:
347 osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);
348 break;
349 case ISO7816_E_ABORT_REQ:
350 /* FIXME */
351 break;
352 default:
353 OSMO_ASSERT(0);
354 break;
355 }
356}
357
358static const struct osmo_fsm_state iso7816_3_states[] = {
359 [ISO7816_S_RESET] = {
360 .name = "RESET",
361 .in_event_mask = S(ISO7816_E_RESET_REL_IND),
362 .out_state_mask = S(ISO7816_S_WAIT_ATR) |
363 S(ISO7816_S_RESET),
364 .action = iso7816_3_reset_action,
365 .onenter = iso7816_3_reset_onenter,
366 },
367 [ISO7816_S_WAIT_ATR] = {
368 .name = "WAIT_ATR",
369 .in_event_mask = S(ISO7816_E_RX_SINGLE),
370 .out_state_mask = S(ISO7816_S_RESET) |
371 S(ISO7816_S_IN_ATR),
372 .action = iso7816_3_wait_atr_action,
373 },
374 [ISO7816_S_IN_ATR] = {
375 .name = "IN_ATR",
376 .in_event_mask = S(ISO7816_E_RX_SINGLE) |
377 S(ISO7816_E_RX_ERR_IND) |
378 S(ISO7816_E_ATR_DONE_IND),
379 .out_state_mask = S(ISO7816_S_RESET) |
380 S(ISO7816_S_IN_ATR) |
381 S(ISO7816_S_WAIT_TPDU),
382 .action = iso7816_3_in_atr_action,
383 },
384 [ISO7816_S_WAIT_TPDU] = {
385 .name = "WAIT_TPDU",
386 .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD),
387 .out_state_mask = S(ISO7816_S_RESET) |
388 S(ISO7816_S_WAIT_TPDU) |
389 S(ISO7816_S_IN_TPDU) |
390 S(ISO7816_S_IN_PPS_REQ),
391 .action = iso7816_3_wait_tpdu_action,
392 .onenter = iso7816_3_wait_tpdu_onenter,
393 },
394 [ISO7816_S_IN_TPDU] = {
395 .name = "IN_TPDU",
396 .in_event_mask = S(ISO7816_E_RX_SINGLE) |
397 S(ISO7816_E_RX_COMPL) |
398 S(ISO7816_E_TX_COMPL) |
399 S(ISO7816_E_RX_ERR_IND) |
400 S(ISO7816_E_TX_ERR_IND) |
401 S(ISO7816_E_TPDU_DONE_IND),
402 .out_state_mask = S(ISO7816_S_RESET) |
403 S(ISO7816_S_WAIT_TPDU) |
404 S(ISO7816_S_IN_TPDU),
405 .action = iso7816_3_in_tpdu_action,
406 },
407 [ISO7816_S_IN_PPS_REQ] = {
408 .name = "IN_PPS_REQ",
409 .in_event_mask = 0, /* FIXME */
410 .out_state_mask = S(ISO7816_S_RESET) |
411 S(ISO7816_S_WAIT_TPDU) |
412 S(ISO7816_S_IN_PPS_REQ) |
413 S(ISO7816_S_WAIT_PPS_RSP),
414 },
415 [ISO7816_S_WAIT_PPS_RSP] = {
416 .name = "WAIT_PPS_RESP",
417 .in_event_mask = 0, /* FIXME */
418 .out_state_mask = S(ISO7816_S_RESET) |
419 S(ISO7816_S_WAIT_TPDU) |
420 S(ISO7816_S_WAIT_PPS_RSP) |
421 S(ISO7816_S_IN_PPS_RSP),
422 },
423 [ISO7816_S_IN_PPS_RSP] = {
424 .name = "IN_PPS_RESP",
425 .in_event_mask = 0, /* FIXME */
426 .out_state_mask = S(ISO7816_S_RESET) |
427 S(ISO7816_S_WAIT_TPDU) |
428 S(ISO7816_S_IN_PPS_RSP),
429 },
430};
431static struct osmo_fsm iso7816_3_fsm = {
432 .name = "ISO7816-3",
433 .states = iso7816_3_states,
434 .num_states = ARRAY_SIZE(iso7816_3_states),
435 .log_subsys = DISO7816,
436 .event_names = iso7816_3_event_names,
437 .allstate_action = iso7816_3_allstate_action,
438 .allstate_event_mask = S(ISO7816_E_WTIME_EXP) |
439 S(ISO7816_E_CARD_REMOVAL) |
440 S(ISO7816_E_POWER_DN_IND) |
441 S(ISO7816_E_RESET_ACT_IND) |
442 S(ISO7816_E_HW_ERR_IND) |
443 S(ISO7816_E_ABORT_REQ),
444};
445
446/***********************************************************************
447 * ATR FSM
448 ***********************************************************************/
449
450struct atr_fsm_priv {
451 uint8_t hist_len; /*!< store the number of expected historical bytes */
452 uint8_t y; /*!< last mask of the upcoming TA, TB, TC, TD interface bytes */
453 uint8_t i; /*!< interface byte subgroup number */
454 struct msgb *atr; /*!< ATR data */
455 uint8_t computed_checksum;
456 uint16_t protocol_support;
457};
458
459/* obtain the [software] guard time in milli-seconds from the atr fsm_inst */
460static uint32_t atr_fi_gt_ms(struct osmo_fsm_inst *fi)
461{
462 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
463 struct iso7816_3_priv *ip;
464
465 OSMO_ASSERT(fi->fsm == &atr_fsm);
466 OSMO_ASSERT(parent_fi);
467 ip = get_iso7816_3_priv(parent_fi);
468
469 return ip->guard_time_ms;
470}
471
472/* obtain the 'byte' parmeter of an ISO7816_E_RX event */
473static uint8_t get_rx_byte_evt(struct osmo_fsm_inst *fi, void *data)
474{
475 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
476 uint8_t byte = *(uint8_t *)data;
477
478 /* apply inverse convention */
479 if (ip->convention_convert)
480 byte = convention_convert_lut[byte];
481
482 return byte;
483}
484
485/* append a single byte to the ATR */
486static int atr_append_byte(struct osmo_fsm_inst *fi, uint8_t byte)
487{
488 struct atr_fsm_priv *atp = fi->priv;
489
490 if (!msgb_tailroom(atp->atr)) {
491 LOGPFSML(fi, LOGL_ERROR, "ATR overflow !?!");
492 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_SW_ERR_IND, NULL);
493 return -1;
494 }
495 msgb_put_u8(atp->atr, byte);
496 return 0;
497}
498
499static void atr_wait_ts_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
500{
501 struct atr_fsm_priv *atp = fi->priv;
502
503 /* reset state to its initial value */
504 atp->hist_len = 0;
505 atp->y = 0;
506 atp->i = 0;
507 if (!atp->atr)
508 atp->atr = msgb_alloc_c(fi, 33, "ATR"); /* TS + 32 chars */
509 else
510 msgb_reset(atp->atr);
511 atp->computed_checksum = 0;
512 atp->protocol_support = 0;
513}
514
515static void atr_wait_ts_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
516{
517 struct atr_fsm_priv *atp = fi->priv;
518 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
519 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
520 uint8_t byte;
521
522 switch (event) {
523 case ISO7816_E_RX_SINGLE:
524 OSMO_ASSERT(msgb_length(atp->atr) == 0);
525restart:
526 byte = get_rx_byte_evt(parent_fi, data);
527 LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);
528 switch (byte) {
529 case 0x23:
530 /* direct convention used, but decoded using inverse
531 * convention (a parity error should also have occurred) */
532 /* fall-through */
533 case 0x30:
534 /* inverse convention used, but decoded using direct
535 * convention (a parity error should also have occurred) */
536 ip->convention_convert = !ip->convention_convert;
537 goto restart;
538 break;
539 case 0x3b: /* direct convention used and correctly decoded */
540 /* fall-through */
541 case 0x3f: /* inverse convention used and correctly decoded */
542 atr_append_byte(fi, byte);
543 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_T0, atr_fi_gt_ms(fi), T_GUARD);
544 break;
545 default:
546 LOGPFSML(fi, LOGL_ERROR, "Invalid TS received: 0x%02X\n", byte);
547 /* FIXME: somehow indiicate to user */
548 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_SW_ERR_IND, NULL);
549 break;
550 }
551 atp->i = 0; /* first interface byte sub-group is coming (T0 is kind of TD0) */
552 break;
553 default:
554 OSMO_ASSERT(0);
555 }
556}
557
558static void atr_wait_tX_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
559{
560 struct atr_fsm_priv *atp = fi->priv;
561 uint32_t guard_time_ms = atr_fi_gt_ms(fi);
562 uint8_t byte;
563
564 switch (event) {
565 case ISO7816_E_RX_SINGLE:
566 byte = get_rx_byte_evt(fi->proc.parent, data);
567 LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);
568 atr_append_byte(fi, byte);
569 switch (fi->state) {
570 case ATR_S_WAIT_T0: /* see ISO/IEC 7816-3:2006 section 8.2.2 */
571 case ATR_S_WAIT_TD: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
572 if (fi->state == ATR_S_WAIT_T0) {
573 /* save number of hist. bytes */
574 atp->hist_len = (byte & 0x0f);
575 } else {
576 /* remember supported protocol to know if TCK will be present */
577 atp->protocol_support |= (1<<(byte & 0x0f));
578 }
579 atp->y = (byte & 0xf0); /* remember incoming interface bytes */
580 atp->i++;
581 if (atp->y & 0x10) {
582 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TA, guard_time_ms, T_GUARD);
583 break;
584 }
585 /* fall-through */
586 case ATR_S_WAIT_TA: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
587 if (atp->y & 0x20) {
588 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TB, guard_time_ms, T_GUARD);
589 break;
590 }
591 /* fall-through */
592 case ATR_S_WAIT_TB: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
593 if (atp->y & 0x40) {
594 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TC, guard_time_ms, T_GUARD);
595 break;
596 }
597 /* fall-through */
598 case ATR_S_WAIT_TC: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
599 if (atp->y & 0x80) {
600 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TD, guard_time_ms, T_GUARD);
601 break;
602 } else if (atp->hist_len) {
603 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_HIST, guard_time_ms, T_GUARD);
604 break;
605 }
606 /* fall-through */
607 case ATR_S_WAIT_HIST: /* see ISO/IEC 7816-3:2006 section 8.2.4 */
608 if (atp->hist_len)
609 atp->hist_len--;
610 if (atp->hist_len == 0) {
611 if (atp->protocol_support > 1) {
612 /* wait for check byte */
613 osmo_fsm_inst_state_chg_ms(fi, ATR_S_WAIT_TCK,
614 guard_time_ms, T_GUARD);
615 break;
616 }
617 } else {
618 break;
619 }
620 /* fall-through */
621 case ATR_S_WAIT_TCK: /* see ISO/IEC 7816-3:2006 section 8.2.5 */
622 /* verify checksum if present */
623 if (fi->state == ATR_S_WAIT_TCK) {
624 uint8_t ui;
625 uint8_t *atr = msgb_data(atp->atr);
626 LOGPFSML(fi, LOGL_INFO, "Complete ATR: %s\n", msgb_hexdump(atp->atr));
627 for (ui = 1; ui < msgb_length(atp->atr)-1; ui++) {
628 atp->computed_checksum ^= atr[ui];
629 }
630 if (atp->computed_checksum != byte) {
631 /* checkum error. report to user? */
632 LOGPFSML(fi, LOGL_ERROR,
633 "computed checksum %02x doesn't match TCK=%02x\n",
634 atp->computed_checksum, byte);
635 }
636 /* ATR complete; notify parent */
637 osmo_fsm_inst_state_chg(fi, ATR_S_DONE, 0, 0);
638 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_ATR_DONE_IND, atp->atr);
639 }
640 break;
641 default:
642 OSMO_ASSERT(0);
643 }
644 break;
645 default:
646 OSMO_ASSERT(0);
647 }
648}
649
650static const struct osmo_fsm_state atr_states[] = {
651 [ATR_S_WAIT_TS] = {
652 .name = "WAIT_TS",
653 .in_event_mask = S(ISO7816_E_RX_SINGLE),
654 .out_state_mask = S(ATR_S_WAIT_TS) |
655 S(ATR_S_WAIT_T0),
656 .action = atr_wait_ts_action,
657 .onenter = atr_wait_ts_onenter,
658 },
659 [ATR_S_WAIT_T0] = {
660 .name = "WAIT_T0",
661 .in_event_mask = S(ISO7816_E_RX_SINGLE),
662 .out_state_mask = S(ATR_S_WAIT_TA) |
663 S(ATR_S_WAIT_TB) |
664 S(ATR_S_WAIT_TC) |
665 S(ATR_S_WAIT_TD) |
666 S(ATR_S_WAIT_HIST) |
667 S(ATR_S_WAIT_TCK) |
668 S(ATR_S_WAIT_T0),
669 .action = atr_wait_tX_action,
670 },
671 [ATR_S_WAIT_TA] = {
672 .name = "WAIT_TA",
673 .in_event_mask = S(ISO7816_E_RX_SINGLE),
674 .out_state_mask = S(ATR_S_WAIT_TB) |
675 S(ATR_S_WAIT_TC) |
676 S(ATR_S_WAIT_TD) |
677 S(ATR_S_WAIT_HIST) |
678 S(ATR_S_WAIT_TCK) |
679 S(ATR_S_WAIT_T0),
680 .action = atr_wait_tX_action,
681 },
682 [ATR_S_WAIT_TB] = {
683 .name = "WAIT_TB",
684 .in_event_mask = S(ISO7816_E_RX_SINGLE),
685 .out_state_mask = S(ATR_S_WAIT_TC) |
686 S(ATR_S_WAIT_TD) |
687 S(ATR_S_WAIT_HIST) |
688 S(ATR_S_WAIT_TCK) |
689 S(ATR_S_WAIT_T0),
690 .action = atr_wait_tX_action,
691 },
692 [ATR_S_WAIT_TC] = {
693 .name = "WAIT_TC",
694 .in_event_mask = S(ISO7816_E_RX_SINGLE),
695 .out_state_mask = S(ATR_S_WAIT_TD) |
696 S(ATR_S_WAIT_HIST) |
697 S(ATR_S_WAIT_TCK) |
698 S(ATR_S_WAIT_T0),
699 .action = atr_wait_tX_action,
700 },
701 [ATR_S_WAIT_TD] = {
702 .name = "WAIT_TD",
703 .in_event_mask = S(ISO7816_E_RX_SINGLE),
704 .out_state_mask = S(ATR_S_WAIT_TA) |
705 S(ATR_S_WAIT_TB) |
706 S(ATR_S_WAIT_TC) |
707 S(ATR_S_WAIT_TD) |
708 S(ATR_S_WAIT_HIST) |
709 S(ATR_S_WAIT_TCK) |
710 S(ATR_S_WAIT_T0),
711 .action = atr_wait_tX_action,
712 },
713 [ATR_S_WAIT_HIST] = {
714 .name = "WAIT_HIST",
715 .in_event_mask = S(ISO7816_E_RX_SINGLE),
716 .out_state_mask = S(ATR_S_WAIT_TCK) |
717 S(ATR_S_WAIT_T0),
718 .action = atr_wait_tX_action,
719 },
720 [ATR_S_WAIT_TCK] = {
721 .name = "WAIT_TCK",
722 .in_event_mask = S(ISO7816_E_RX_SINGLE),
723 .out_state_mask = S(ATR_S_DONE),
724 .action = atr_wait_tX_action,
725 },
726 [ATR_S_DONE] = {
727 .name = "DONE",
728 .in_event_mask = 0,
729 .out_state_mask = S(ATR_S_WAIT_T0),
730 //.action = atr_done_action,
731 },
732
733};
734static struct osmo_fsm atr_fsm = {
735 .name = "ATR",
736 .states = atr_states,
737 .num_states = ARRAY_SIZE(atr_states),
738 .log_subsys = DATR,
739 .event_names = iso7816_3_event_names,
740};
741
742/***********************************************************************
743 * PPS FSM
744 ***********************************************************************/
745
746static const struct osmo_fsm_state pps_states[] = {
747 [PPS_S_WAIT_PPSS] = {
748 .name = "WAIT_PPSS",
749 },
750 [PPS_S_WAIT_PPS0] = {
751 .name = "WAIT_PPS0",
752 },
753 [PPS_S_WAIT_PPS1] = {
754 .name = "WAIT_PPS1",
755 },
756 [PPS_S_WAIT_PPS2] = {
757 .name = "WAIT_PPS2",
758 },
759 [PPS_S_WAIT_PPS3] = {
760 .name = "WAIT_PPS3",
761 },
762 [PPS_S_WAIT_PCK] = {
763 .name = "WAIT_PCK",
764 },
765 [PPS_S_WAIT_END] = {
766 .name = "WAIT_END",
767 },
768};
769
770static struct osmo_fsm pps_fsm = {
771 .name = "PPS",
772 .states = pps_states,
773 .num_states = ARRAY_SIZE(pps_states),
774 .log_subsys = DPPS,
775 .event_names = iso7816_3_event_names,
776};
777
778/***********************************************************************
779 * TPDU FSM
780 ***********************************************************************/
781
782struct tpdu_fsm_priv {
783 struct msgb *tpdu;
784};
785
786/* type-safe method to obtain iso7816_3_priv from fi */
787static struct tpdu_fsm_priv *get_tpdu_fsm_priv(struct osmo_fsm_inst *fi)
788{
789 OSMO_ASSERT(fi);
790 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
791 return (struct tpdu_fsm_priv *) fi->priv;
792}
793
794
795static void tpdu_s_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
796{
797 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
798 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
799 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
800 struct osim_apdu_cmd_hdr *tpduh;
801
802 switch (event) {
803 case ISO7816_E_XCEIVE_TPDU_CMD:
804 /* start transmission of a TPDU by sending the 5-byte header */
805 tfp->tpdu = (struct msgb *)data;
806 OSMO_ASSERT(msgb_length(tfp->tpdu) >= sizeof(*tpduh));
807 tfp->tpdu->l2h = msgb_data(tfp->tpdu) + sizeof(*tpduh);
808 tpduh = msgb_data(tfp->tpdu);
809 LOGPFSML(fi, LOGL_DEBUG, "Transmitting TPDU header %s via UART\n",
810 osmo_hexdump_nospc((uint8_t *) tpduh, sizeof(*tpduh)));
811 osmo_fsm_inst_state_chg(fi, TPDU_S_TX_HDR, 0, 0);
Harald Welte02dd9112019-10-01 08:55:29 +0200812 card_uart_tx(ip->uart, (uint8_t *) tpduh, sizeof(*tpduh));
Harald Welte06348362019-05-19 00:45:17 +0200813 break;
814 default:
815 OSMO_ASSERT(0);
816 }
817}
818
819static void tpdu_s_tx_hdr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
820{
821 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
822 switch (event) {
823 case ISO7816_E_TX_COMPL:
824 /* Rx of single byte is already enabled by previous card_uart_tx() call */
825 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
826 break;
827 default:
828 OSMO_ASSERT(0);
829 }
830}
831
832
833
834static void tpdu_s_procedure_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
835{
836 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
837 struct osim_apdu_cmd_hdr *tpduh = msgb_data(tfp->tpdu);
838 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
839 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
840 uint8_t byte;
841
842 switch (event) {
843 case ISO7816_E_RX_SINGLE:
844 byte = get_rx_byte_evt(fi->proc.parent, data);
845 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
846 if (byte == 0x60) {
847 /* NULL: wait for another procedure byte */
848 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
849 } else if ((byte >= 0x60 && byte <= 0x6f) || (byte >= 0x90 && byte <= 0x9f)) {
850 //msgb_apdu_sw(tfp->apdu) = byte << 8;
851 msgb_put(tfp->tpdu, byte);
852 /* receive second SW byte (SW2) */
853 osmo_fsm_inst_state_chg(fi, TPDU_S_SW2, 0, 0);
854 break;
855 } else if (byte == tpduh->ins) {
856 if (msgb_l2len(tfp->tpdu)) {
857 /* transmit all remaining bytes */
Harald Welte02dd9112019-10-01 08:55:29 +0200858 card_uart_tx(ip->uart, msgb_l2(tfp->tpdu), msgb_l2len(tfp->tpdu));
Harald Welte06348362019-05-19 00:45:17 +0200859 osmo_fsm_inst_state_chg(fi, TPDU_S_TX_REMAINING, 0, 0);
860 } else {
861 card_uart_set_rx_threshold(ip->uart, tpduh->p3);
862 osmo_fsm_inst_state_chg(fi, TPDU_S_RX_REMAINING, 0, 0);
863 }
864 } else if (byte == (tpduh->ins ^ 0xFF)) {
865 osmo_panic("unsupported single-byte T=0 case");
866 /* FIXME: transmit single byte then wait for proc */
867 //osmo_fsm_inst_state_chg(fi, TPDU_S_xX_SINGLE, 0, 0);
868 //osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
869 } else
870 OSMO_ASSERT(0);
871 break;
872 default:
873 OSMO_ASSERT(0);
874 }
875}
876
877/* UART is transmitting remaining data; we wait for ISO7816_E_TX_COMPL */
878static void tpdu_s_tx_remaining_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
879{
880 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
881 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
882
883 switch (event) {
884 case ISO7816_E_TX_COMPL:
885 card_uart_set_rx_threshold(ip->uart, 1);
886 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
887 break;
888 default:
889 OSMO_ASSERT(0);
890 }
891}
892
893/* UART is transmitting single byte of data; we wait for ISO7816_E_TX_COMPL */
894static void tpdu_s_tx_single_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
895{
896 switch (event) {
897 case ISO7816_E_TX_COMPL:
898 /* TODO: increase pointer/counter? */
899 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
900 break;
901 default:
902 OSMO_ASSERT(0);
903 }
904}
905
906/* UART is receiving remaining data; we wait for ISO7816_E_RX_COMPL */
907static void tpdu_s_rx_remaining_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
908{
909 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
910 struct osim_apdu_cmd_hdr *tpduh = msgb_data(tfp->tpdu);
911 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
912 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
913 int rc;
914
915 switch (event) {
916 case ISO7816_E_RX_COMPL:
917 /* retrieve pending byte(s) */
918 rc = card_uart_rx(ip->uart, msgb_l2(tfp->tpdu), tpduh->p3);
919 if (rc != tpduh->p3)
920 LOGPFSML(fi, LOGL_ERROR, "expected %u bytes; read %d\n", tpduh->p3, rc);
921 card_uart_set_rx_threshold(ip->uart, 1);
922 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
923 break;
924 default:
925 OSMO_ASSERT(0);
926 }
927}
928
929/* UART is receiving single byte of data; we wait for ISO7816_E_RX_SINGLE */
930static void tpdu_s_rx_single_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
931{
932 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
933 uint8_t byte;
934
935 switch (event) {
936 case ISO7816_E_RX_SINGLE:
937 byte = get_rx_byte_evt(fi->proc.parent, data);
938 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
939 /* TODO: record byte */
940 /* FIXME: determine if number of expected bytes received */
941 if (0) {
942 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
943 } else
944 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
945 break;
946 default:
947 OSMO_ASSERT(0);
948 }
949}
950
951static void tpdu_s_sw1_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
952{
953 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
954 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
955 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
956 uint8_t byte;
957
958 switch (event) {
959 case ISO7816_E_RX_SINGLE:
960 byte = get_rx_byte_evt(fi->proc.parent, data);
961 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
962 /* record byte */
963 //msgb_apdu_sw(tfp->apdu) = byte << 8;
964 msgb_put_u8(tfp->tpdu, byte);
965 card_uart_set_rx_threshold(ip->uart, 1);
966 osmo_fsm_inst_state_chg(fi, TPDU_S_SW2, 0, 0);
967 break;
968 default:
969 OSMO_ASSERT(0);
970 }
971}
972
973static void tpdu_s_sw2_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
974{
975 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
976 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
977 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
978 uint8_t byte;
979
980 switch (event) {
981 case ISO7816_E_RX_SINGLE:
982 byte = get_rx_byte_evt(fi->proc.parent, data);
983 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
984 /* record SW2 byte */
985 //msgb_apdu_sw(tfp->apdu) &= 0xFF00;
986 //msgb_apdu_sw(tfp->apdu) |= byte;
987 msgb_put_u8(tfp->tpdu, byte);
988 osmo_fsm_inst_state_chg(fi, TPDU_S_DONE, 0, 0);
989 /* Notify parent FSM */
990 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, tfp->tpdu);
991 break;
992 default:
993 OSMO_ASSERT(0);
994 }
995}
996
997static void tpdu_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
998{
999 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
1000
1001 switch (event) {
1002 case ISO7816_E_RX_ERR_IND:
1003 case ISO7816_E_TX_ERR_IND:
1004 /* FIXME: handle this in some different way */
1005 osmo_fsm_inst_state_chg(fi, TPDU_S_DONE, 0, 0);
1006 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, NULL);
1007 break;
1008 case ISO7816_E_TPDU_CLEAR_REQ:
1009 osmo_fsm_inst_state_chg(fi, TPDU_S_INIT, 0, 0);
1010 break;
1011 }
1012}
1013
1014static const struct osmo_fsm_state tpdu_states[] = {
1015 [TPDU_S_INIT] = {
1016 .name = "INIT",
1017 .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD) |
1018 S(ISO7816_E_TX_COMPL),
1019 .out_state_mask = S(TPDU_S_INIT) |
1020 S(TPDU_S_TX_HDR),
1021 .action = tpdu_s_init_action,
1022 },
1023 [TPDU_S_TX_HDR] = {
1024 .name = "TX_HDR",
1025 .in_event_mask = S(ISO7816_E_TX_COMPL),
1026 .out_state_mask = S(TPDU_S_INIT) |
1027 S(TPDU_S_PROCEDURE),
1028 .action = tpdu_s_tx_hdr_action,
1029 },
1030 [TPDU_S_PROCEDURE] = {
1031 .name = "PROCEDURE",
1032 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1033 .out_state_mask = S(TPDU_S_INIT) |
1034 S(TPDU_S_PROCEDURE) |
1035 S(TPDU_S_RX_REMAINING) |
1036 S(TPDU_S_RX_SINGLE) |
1037 S(TPDU_S_TX_REMAINING) |
1038 S(TPDU_S_TX_SINGLE) |
1039 S(TPDU_S_SW2),
1040 .action = tpdu_s_procedure_action,
1041 },
1042 [TPDU_S_TX_REMAINING] = {
1043 .name = "TX_REMAINING",
1044 .in_event_mask = S(ISO7816_E_TX_COMPL),
1045 .out_state_mask = S(TPDU_S_INIT) |
1046 S(TPDU_S_SW1),
1047 .action = tpdu_s_tx_remaining_action,
1048 },
1049 [TPDU_S_TX_SINGLE] = {
1050 .name = "TX_SINGLE",
1051 .in_event_mask = S(ISO7816_E_TX_COMPL),
1052 .out_state_mask = S(TPDU_S_INIT) |
1053 S(TPDU_S_PROCEDURE),
1054 .action = tpdu_s_tx_single_action,
1055 },
1056 [TPDU_S_RX_REMAINING] = {
1057 .name = "RX_REMAINING",
1058 .in_event_mask = S(ISO7816_E_RX_COMPL),
1059 .out_state_mask = S(TPDU_S_INIT) |
1060 S(TPDU_S_SW1),
1061 .action = tpdu_s_rx_remaining_action,
1062 },
1063 [TPDU_S_RX_SINGLE] = {
1064 .name = "RX_SINGLE",
1065 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1066 .out_state_mask = S(TPDU_S_INIT) |
1067 S(TPDU_S_PROCEDURE),
1068 .action = tpdu_s_rx_single_action,
1069 },
1070 [TPDU_S_SW1] = {
1071 .name = "SW1",
1072 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1073 .out_state_mask = S(TPDU_S_INIT) |
1074 S(TPDU_S_SW2),
1075 .action = tpdu_s_sw1_action,
1076 },
1077 [TPDU_S_SW2] = {
1078 .name = "SW2",
1079 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1080 .out_state_mask = S(TPDU_S_INIT) |
1081 S(TPDU_S_DONE),
1082 .action = tpdu_s_sw2_action,
1083 },
1084 [TPDU_S_DONE] = {
1085 .name = "DONE",
1086 .in_event_mask = 0,
1087 .out_state_mask = S(TPDU_S_INIT),
1088 .action = NULL,
1089 },
1090};
1091static struct osmo_fsm tpdu_fsm = {
1092 .name = "TPDU",
1093 .states = tpdu_states,
1094 .num_states = ARRAY_SIZE(tpdu_states),
1095 .allstate_event_mask = S(ISO7816_E_RX_ERR_IND) |
1096 S(ISO7816_E_TX_ERR_IND) |
1097 S(ISO7816_E_TPDU_CLEAR_REQ),
1098 .allstate_action = tpdu_allstate_action,
1099 .log_subsys = DTPDU,
1100 .event_names = iso7816_3_event_names,
1101};
1102
1103struct osmo_fsm_inst *iso7816_fsm_alloc(void *ctx, int log_level, const char *id,
1104 struct card_uart *cuart, iso7816_user_cb user_cb,
1105 void *user_priv)
1106{
1107 struct iso7816_3_priv *ip;
1108 struct osmo_fsm_inst *fi;
1109
1110 fi = osmo_fsm_inst_alloc(&iso7816_3_fsm, ctx, NULL, log_level, id);
1111 ip = talloc_zero(fi, struct iso7816_3_priv);
1112 if (!ip)
1113 goto out_fi;
1114 fi->priv = ip;
1115
1116 ip->uart = cuart;
1117 cuart->priv = fi;
1118 cuart->handle_event = tpdu_uart_notification;
1119
1120 ip->user_cb = user_cb;
1121 ip->user_priv = user_priv;
1122
1123 ip->atr_fi = osmo_fsm_inst_alloc_child(&atr_fsm, fi, ISO7816_E_SW_ERR_IND);
1124 if (!ip->atr_fi)
1125 goto out_fi;
1126 ip->atr_fi->priv = talloc_zero(ip->atr_fi, struct atr_fsm_priv);
1127 if (!ip->atr_fi->priv)
1128 goto out_atr;
1129
1130 ip->tpdu_fi = osmo_fsm_inst_alloc_child(&tpdu_fsm, fi, ISO7816_E_SW_ERR_IND);
1131 if (!ip->tpdu_fi)
1132 goto out_atr;
1133 ip->tpdu_fi->priv = talloc_zero(ip->tpdu_fi, struct tpdu_fsm_priv);
1134 if (!ip->tpdu_fi->priv)
1135 goto out_tpdu;
1136
1137#if 0
1138 ip->pps_fi = osmo_fsm_inst_alloc_child(&pps_fsm, fi, ISO7816_E_SW_ERR_IND);
1139 if (!ip->pps_fi)
1140 goto out_tpdu;
1141 ip->pps_fi->priv = talloc_zero(ip->pps_fi, struct pps_fsm_priv);
1142 if (!ip->pps_fi->priv)
1143 goto out_pps;
1144#endif
1145
1146 /* This ensures the 'onenter' function of the initial state is called */
1147 osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);
1148
1149 return fi;
1150
1151#if 0
1152out_pps:
1153 osmo_fsm_inst_free(ip->pps_fi);
1154#endif
1155out_tpdu:
1156 osmo_fsm_inst_free(ip->tpdu_fi);
1157out_atr:
1158 osmo_fsm_inst_free(ip->atr_fi);
1159out_fi:
1160 osmo_fsm_inst_free(fi);
1161 cuart->priv = NULL;
1162 return NULL;
1163}
1164
1165void *iso7816_fsm_get_user_priv(struct osmo_fsm_inst *fi)
1166{
1167 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
1168 return ip->user_priv;
1169}
1170
1171
1172static __attribute__((constructor)) void on_dso_load_iso7816(void)
1173{
1174 osmo_fsm_register(&iso7816_3_fsm);
1175 osmo_fsm_register(&atr_fsm);
1176 osmo_fsm_register(&tpdu_fsm);
1177 osmo_fsm_register(&pps_fsm);
1178}