blob: e173030648c2d35a7edd3931e5aad17b6a156320 [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
Harald Welte65087832019-10-01 09:16:49 +0200782/* In this FSM weu use the msgb for the TPDU as follows:
783 * - 5-byte TPDU header is at msg->data
784 * - COMMAND TPDU:
785 * - command bytes are provided after the header at msg->l2h
786 * - in case of incremental transmission, l3h points to next to-be-transmitted byte
787 * - RESPONSE TPDU:
788 * - any response bytes are stored after the header at msg->l2h
789 */
790
791static inline struct osim_apdu_cmd_hdr *msgb_tpdu_hdr(struct msgb *msg) {
792 return (struct osim_apdu_cmd_hdr *) msgb_data(msg);
793}
794
Harald Welte06348362019-05-19 00:45:17 +0200795struct tpdu_fsm_priv {
796 struct msgb *tpdu;
Harald Welte65087832019-10-01 09:16:49 +0200797 bool is_command; /* is this a command TPDU (true) or a response (false) */
Harald Welte06348362019-05-19 00:45:17 +0200798};
799
800/* type-safe method to obtain iso7816_3_priv from fi */
801static struct tpdu_fsm_priv *get_tpdu_fsm_priv(struct osmo_fsm_inst *fi)
802{
803 OSMO_ASSERT(fi);
804 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
805 return (struct tpdu_fsm_priv *) fi->priv;
806}
807
808
809static void tpdu_s_init_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
810{
811 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
812 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
813 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
814 struct osim_apdu_cmd_hdr *tpduh;
815
816 switch (event) {
817 case ISO7816_E_XCEIVE_TPDU_CMD:
818 /* start transmission of a TPDU by sending the 5-byte header */
819 tfp->tpdu = (struct msgb *)data;
820 OSMO_ASSERT(msgb_length(tfp->tpdu) >= sizeof(*tpduh));
821 tfp->tpdu->l2h = msgb_data(tfp->tpdu) + sizeof(*tpduh);
Harald Welte65087832019-10-01 09:16:49 +0200822 if (msgb_l2len(tfp->tpdu)) {
823 tfp->is_command = true;
824 tfp->tpdu->l3h = tfp->tpdu->l2h; /* next tx byte == first byte of body */
825 } else
826 tfp->is_command = false;
827 tpduh = msgb_tpdu_hdr(tfp->tpdu);
828 LOGPFSML(fi, LOGL_DEBUG, "Transmitting %s TPDU header %s via UART\n",
829 tfp->is_command ? "COMMAND" : "RESPONSE",
Harald Welte06348362019-05-19 00:45:17 +0200830 osmo_hexdump_nospc((uint8_t *) tpduh, sizeof(*tpduh)));
831 osmo_fsm_inst_state_chg(fi, TPDU_S_TX_HDR, 0, 0);
Harald Welte02dd9112019-10-01 08:55:29 +0200832 card_uart_tx(ip->uart, (uint8_t *) tpduh, sizeof(*tpduh));
Harald Welte06348362019-05-19 00:45:17 +0200833 break;
834 default:
835 OSMO_ASSERT(0);
836 }
837}
838
839static void tpdu_s_tx_hdr_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
840{
841 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
842 switch (event) {
843 case ISO7816_E_TX_COMPL:
844 /* Rx of single byte is already enabled by previous card_uart_tx() call */
845 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
846 break;
847 default:
848 OSMO_ASSERT(0);
849 }
850}
851
852
853
854static void tpdu_s_procedure_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
855{
856 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
Harald Welte65087832019-10-01 09:16:49 +0200857 struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
Harald Welte06348362019-05-19 00:45:17 +0200858 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
859 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
860 uint8_t byte;
861
862 switch (event) {
863 case ISO7816_E_RX_SINGLE:
864 byte = get_rx_byte_evt(fi->proc.parent, data);
865 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
866 if (byte == 0x60) {
867 /* NULL: wait for another procedure byte */
868 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
869 } else if ((byte >= 0x60 && byte <= 0x6f) || (byte >= 0x90 && byte <= 0x9f)) {
870 //msgb_apdu_sw(tfp->apdu) = byte << 8;
871 msgb_put(tfp->tpdu, byte);
872 /* receive second SW byte (SW2) */
873 osmo_fsm_inst_state_chg(fi, TPDU_S_SW2, 0, 0);
874 break;
875 } else if (byte == tpduh->ins) {
Harald Welte65087832019-10-01 09:16:49 +0200876 if (tfp->is_command) {
Harald Welte06348362019-05-19 00:45:17 +0200877 /* transmit all remaining bytes */
Harald Welte02dd9112019-10-01 08:55:29 +0200878 card_uart_tx(ip->uart, msgb_l2(tfp->tpdu), msgb_l2len(tfp->tpdu));
Harald Welte06348362019-05-19 00:45:17 +0200879 osmo_fsm_inst_state_chg(fi, TPDU_S_TX_REMAINING, 0, 0);
880 } else {
881 card_uart_set_rx_threshold(ip->uart, tpduh->p3);
882 osmo_fsm_inst_state_chg(fi, TPDU_S_RX_REMAINING, 0, 0);
883 }
884 } else if (byte == (tpduh->ins ^ 0xFF)) {
Harald Welte65087832019-10-01 09:16:49 +0200885 /* transmit/recieve single byte then wait for proc */
886 if (tfp->is_command) {
887 /* transmit *next*, not first byte */
888 OSMO_ASSERT(msgb_l3len(tfp->tpdu) >= 0);
889 card_uart_tx(ip->uart, msgb_l3(tfp->tpdu), 1);
890 osmo_fsm_inst_state_chg(fi, TPDU_S_TX_SINGLE, 0, 0);
891 } else {
892 osmo_fsm_inst_state_chg(fi, TPDU_S_RX_SINGLE, 0, 0);
893 }
Harald Welte06348362019-05-19 00:45:17 +0200894 } else
895 OSMO_ASSERT(0);
896 break;
897 default:
898 OSMO_ASSERT(0);
899 }
900}
901
902/* UART is transmitting remaining data; we wait for ISO7816_E_TX_COMPL */
903static void tpdu_s_tx_remaining_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
904{
905 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
906 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
907
908 switch (event) {
909 case ISO7816_E_TX_COMPL:
910 card_uart_set_rx_threshold(ip->uart, 1);
911 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
912 break;
913 default:
914 OSMO_ASSERT(0);
915 }
916}
917
918/* UART is transmitting single byte of data; we wait for ISO7816_E_TX_COMPL */
919static void tpdu_s_tx_single_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
920{
Harald Welte65087832019-10-01 09:16:49 +0200921 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
922
Harald Welte06348362019-05-19 00:45:17 +0200923 switch (event) {
924 case ISO7816_E_TX_COMPL:
Harald Welte65087832019-10-01 09:16:49 +0200925 tfp->tpdu->l3h += 1;
926 if (msgb_l3len(tfp->tpdu))
927 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
928 else
929 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
Harald Welte06348362019-05-19 00:45:17 +0200930 break;
931 default:
932 OSMO_ASSERT(0);
933 }
934}
935
936/* UART is receiving remaining data; we wait for ISO7816_E_RX_COMPL */
937static void tpdu_s_rx_remaining_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
938{
939 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
Harald Welte65087832019-10-01 09:16:49 +0200940 struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
Harald Welte06348362019-05-19 00:45:17 +0200941 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
942 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
943 int rc;
944
945 switch (event) {
946 case ISO7816_E_RX_COMPL:
947 /* retrieve pending byte(s) */
948 rc = card_uart_rx(ip->uart, msgb_l2(tfp->tpdu), tpduh->p3);
Harald Welte65087832019-10-01 09:16:49 +0200949 OSMO_ASSERT(rc > 0);
950 msgb_put(tfp->tpdu, rc);
951 if (msgb_l2len(tfp->tpdu) != tpduh->p3) {
952 LOGPFSML(fi, LOGL_ERROR, "expected %u bytes; read %d\n", tpduh->p3,
953 msgb_l2len(tfp->tpdu));
954 }
Harald Welte06348362019-05-19 00:45:17 +0200955 card_uart_set_rx_threshold(ip->uart, 1);
956 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
957 break;
958 default:
959 OSMO_ASSERT(0);
960 }
961}
962
963/* UART is receiving single byte of data; we wait for ISO7816_E_RX_SINGLE */
964static void tpdu_s_rx_single_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
965{
966 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
Harald Welte65087832019-10-01 09:16:49 +0200967 struct osim_apdu_cmd_hdr *tpduh = msgb_tpdu_hdr(tfp->tpdu);
Harald Welte06348362019-05-19 00:45:17 +0200968 uint8_t byte;
969
970 switch (event) {
971 case ISO7816_E_RX_SINGLE:
972 byte = get_rx_byte_evt(fi->proc.parent, data);
973 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
Harald Welte65087832019-10-01 09:16:49 +0200974 msgb_put_u8(tfp->tpdu, byte);
975 /* determine if number of expected bytes received */
976 if (msgb_l2len(tfp->tpdu) == tpduh->p3)
Harald Welte06348362019-05-19 00:45:17 +0200977 osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0);
Harald Welte65087832019-10-01 09:16:49 +0200978 else
Harald Welte06348362019-05-19 00:45:17 +0200979 osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0);
980 break;
981 default:
982 OSMO_ASSERT(0);
983 }
984}
985
986static void tpdu_s_sw1_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
987{
988 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
989 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
990 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
991 uint8_t byte;
992
993 switch (event) {
994 case ISO7816_E_RX_SINGLE:
995 byte = get_rx_byte_evt(fi->proc.parent, data);
996 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
997 /* record byte */
998 //msgb_apdu_sw(tfp->apdu) = byte << 8;
999 msgb_put_u8(tfp->tpdu, byte);
1000 card_uart_set_rx_threshold(ip->uart, 1);
1001 osmo_fsm_inst_state_chg(fi, TPDU_S_SW2, 0, 0);
1002 break;
1003 default:
1004 OSMO_ASSERT(0);
1005 }
1006}
1007
1008static void tpdu_s_sw2_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1009{
1010 struct tpdu_fsm_priv *tfp = get_tpdu_fsm_priv(fi);
1011 struct osmo_fsm_inst *parent_fi = fi->proc.parent;
1012 struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
1013 uint8_t byte;
1014
1015 switch (event) {
1016 case ISO7816_E_RX_SINGLE:
1017 byte = get_rx_byte_evt(fi->proc.parent, data);
1018 LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte);
1019 /* record SW2 byte */
1020 //msgb_apdu_sw(tfp->apdu) &= 0xFF00;
1021 //msgb_apdu_sw(tfp->apdu) |= byte;
1022 msgb_put_u8(tfp->tpdu, byte);
1023 osmo_fsm_inst_state_chg(fi, TPDU_S_DONE, 0, 0);
1024 /* Notify parent FSM */
1025 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, tfp->tpdu);
1026 break;
1027 default:
1028 OSMO_ASSERT(0);
1029 }
1030}
1031
1032static void tpdu_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
1033{
1034 OSMO_ASSERT(fi->fsm == &tpdu_fsm);
1035
1036 switch (event) {
1037 case ISO7816_E_RX_ERR_IND:
1038 case ISO7816_E_TX_ERR_IND:
1039 /* FIXME: handle this in some different way */
1040 osmo_fsm_inst_state_chg(fi, TPDU_S_DONE, 0, 0);
1041 osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_TPDU_DONE_IND, NULL);
1042 break;
1043 case ISO7816_E_TPDU_CLEAR_REQ:
1044 osmo_fsm_inst_state_chg(fi, TPDU_S_INIT, 0, 0);
1045 break;
1046 }
1047}
1048
1049static const struct osmo_fsm_state tpdu_states[] = {
1050 [TPDU_S_INIT] = {
1051 .name = "INIT",
1052 .in_event_mask = S(ISO7816_E_XCEIVE_TPDU_CMD) |
1053 S(ISO7816_E_TX_COMPL),
1054 .out_state_mask = S(TPDU_S_INIT) |
1055 S(TPDU_S_TX_HDR),
1056 .action = tpdu_s_init_action,
1057 },
1058 [TPDU_S_TX_HDR] = {
1059 .name = "TX_HDR",
1060 .in_event_mask = S(ISO7816_E_TX_COMPL),
1061 .out_state_mask = S(TPDU_S_INIT) |
1062 S(TPDU_S_PROCEDURE),
1063 .action = tpdu_s_tx_hdr_action,
1064 },
1065 [TPDU_S_PROCEDURE] = {
1066 .name = "PROCEDURE",
1067 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1068 .out_state_mask = S(TPDU_S_INIT) |
1069 S(TPDU_S_PROCEDURE) |
1070 S(TPDU_S_RX_REMAINING) |
1071 S(TPDU_S_RX_SINGLE) |
1072 S(TPDU_S_TX_REMAINING) |
1073 S(TPDU_S_TX_SINGLE) |
1074 S(TPDU_S_SW2),
1075 .action = tpdu_s_procedure_action,
1076 },
1077 [TPDU_S_TX_REMAINING] = {
1078 .name = "TX_REMAINING",
1079 .in_event_mask = S(ISO7816_E_TX_COMPL),
1080 .out_state_mask = S(TPDU_S_INIT) |
1081 S(TPDU_S_SW1),
1082 .action = tpdu_s_tx_remaining_action,
1083 },
1084 [TPDU_S_TX_SINGLE] = {
1085 .name = "TX_SINGLE",
1086 .in_event_mask = S(ISO7816_E_TX_COMPL),
1087 .out_state_mask = S(TPDU_S_INIT) |
1088 S(TPDU_S_PROCEDURE),
1089 .action = tpdu_s_tx_single_action,
1090 },
1091 [TPDU_S_RX_REMAINING] = {
1092 .name = "RX_REMAINING",
1093 .in_event_mask = S(ISO7816_E_RX_COMPL),
1094 .out_state_mask = S(TPDU_S_INIT) |
1095 S(TPDU_S_SW1),
1096 .action = tpdu_s_rx_remaining_action,
1097 },
1098 [TPDU_S_RX_SINGLE] = {
1099 .name = "RX_SINGLE",
1100 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1101 .out_state_mask = S(TPDU_S_INIT) |
1102 S(TPDU_S_PROCEDURE),
1103 .action = tpdu_s_rx_single_action,
1104 },
1105 [TPDU_S_SW1] = {
1106 .name = "SW1",
1107 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1108 .out_state_mask = S(TPDU_S_INIT) |
1109 S(TPDU_S_SW2),
1110 .action = tpdu_s_sw1_action,
1111 },
1112 [TPDU_S_SW2] = {
1113 .name = "SW2",
1114 .in_event_mask = S(ISO7816_E_RX_SINGLE),
1115 .out_state_mask = S(TPDU_S_INIT) |
1116 S(TPDU_S_DONE),
1117 .action = tpdu_s_sw2_action,
1118 },
1119 [TPDU_S_DONE] = {
1120 .name = "DONE",
1121 .in_event_mask = 0,
1122 .out_state_mask = S(TPDU_S_INIT),
1123 .action = NULL,
1124 },
1125};
1126static struct osmo_fsm tpdu_fsm = {
1127 .name = "TPDU",
1128 .states = tpdu_states,
1129 .num_states = ARRAY_SIZE(tpdu_states),
1130 .allstate_event_mask = S(ISO7816_E_RX_ERR_IND) |
1131 S(ISO7816_E_TX_ERR_IND) |
1132 S(ISO7816_E_TPDU_CLEAR_REQ),
1133 .allstate_action = tpdu_allstate_action,
1134 .log_subsys = DTPDU,
1135 .event_names = iso7816_3_event_names,
1136};
1137
1138struct osmo_fsm_inst *iso7816_fsm_alloc(void *ctx, int log_level, const char *id,
1139 struct card_uart *cuart, iso7816_user_cb user_cb,
1140 void *user_priv)
1141{
1142 struct iso7816_3_priv *ip;
1143 struct osmo_fsm_inst *fi;
1144
1145 fi = osmo_fsm_inst_alloc(&iso7816_3_fsm, ctx, NULL, log_level, id);
1146 ip = talloc_zero(fi, struct iso7816_3_priv);
1147 if (!ip)
1148 goto out_fi;
1149 fi->priv = ip;
1150
1151 ip->uart = cuart;
1152 cuart->priv = fi;
1153 cuart->handle_event = tpdu_uart_notification;
1154
1155 ip->user_cb = user_cb;
1156 ip->user_priv = user_priv;
1157
1158 ip->atr_fi = osmo_fsm_inst_alloc_child(&atr_fsm, fi, ISO7816_E_SW_ERR_IND);
1159 if (!ip->atr_fi)
1160 goto out_fi;
1161 ip->atr_fi->priv = talloc_zero(ip->atr_fi, struct atr_fsm_priv);
1162 if (!ip->atr_fi->priv)
1163 goto out_atr;
1164
1165 ip->tpdu_fi = osmo_fsm_inst_alloc_child(&tpdu_fsm, fi, ISO7816_E_SW_ERR_IND);
1166 if (!ip->tpdu_fi)
1167 goto out_atr;
1168 ip->tpdu_fi->priv = talloc_zero(ip->tpdu_fi, struct tpdu_fsm_priv);
1169 if (!ip->tpdu_fi->priv)
1170 goto out_tpdu;
1171
1172#if 0
1173 ip->pps_fi = osmo_fsm_inst_alloc_child(&pps_fsm, fi, ISO7816_E_SW_ERR_IND);
1174 if (!ip->pps_fi)
1175 goto out_tpdu;
1176 ip->pps_fi->priv = talloc_zero(ip->pps_fi, struct pps_fsm_priv);
1177 if (!ip->pps_fi->priv)
1178 goto out_pps;
1179#endif
1180
1181 /* This ensures the 'onenter' function of the initial state is called */
1182 osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);
1183
1184 return fi;
1185
1186#if 0
1187out_pps:
1188 osmo_fsm_inst_free(ip->pps_fi);
1189#endif
1190out_tpdu:
1191 osmo_fsm_inst_free(ip->tpdu_fi);
1192out_atr:
1193 osmo_fsm_inst_free(ip->atr_fi);
1194out_fi:
1195 osmo_fsm_inst_free(fi);
1196 cuart->priv = NULL;
1197 return NULL;
1198}
1199
1200void *iso7816_fsm_get_user_priv(struct osmo_fsm_inst *fi)
1201{
1202 struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
1203 return ip->user_priv;
1204}
1205
1206
1207static __attribute__((constructor)) void on_dso_load_iso7816(void)
1208{
1209 osmo_fsm_register(&iso7816_3_fsm);
1210 osmo_fsm_register(&atr_fsm);
1211 osmo_fsm_register(&tpdu_fsm);
1212 osmo_fsm_register(&pps_fsm);
1213}