/* Minimal test program for the ISO7816-3 FSM * expects a Smart Card attached to a UART reachable as /dev/ttyXXX * * (C) 2019-2020 by Harald Welte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include #include #include #include #include #include "logging.h" #include "cuart.h" #include "iso7816_fsm.h" static struct card_uart g_cuart; enum test_state { ST_WAIT_ATR, ST_ATR_DONE, ST_IN_TPDU, }; static enum test_state g_tstate = ST_WAIT_ATR; static void fsm_user_cb(struct osmo_fsm_inst *fi, int event, int cause, void *data) { printf("Handle FSM User Event %d: cause=%d, data=%p\n", event, cause, data); switch (event) { case ISO7816_E_ATR_DONE_IND: g_tstate = ST_ATR_DONE; break; case ISO7816_E_TPDU_DONE_IND: printf("======= TPDU: %s\n", msgb_hexdump(data)); msgb_free(data); g_tstate = ST_ATR_DONE; default: break; } } static void *g_tall_ctx; static void signal_handler(int signal) { switch (signal) { case SIGUSR1: talloc_report_full(g_tall_ctx, stderr); break; } } int main(int argc, char **argv) { struct osmo_fsm_inst *fi; uint8_t atr[64]; int rc; g_tall_ctx = talloc_named_const(NULL, 0, "main"); msgb_talloc_ctx_init(g_tall_ctx, 0); osmo_init_logging2(g_tall_ctx, &log_info); osmo_fsm_log_addr(false); signal(SIGUSR1, &signal_handler); if (argc < 2) { fprintf(stderr, "You must specify the UART tty device as argument\n"); exit(2); } printf("Opening UART device %s\n", argv[1]); rc = card_uart_open(&g_cuart, "tty", argv[1]); if (rc < 0) { perror("opening UART"); exit(1); } fi = iso7816_fsm_alloc(NULL, LOGL_DEBUG, "SIM0", &g_cuart, fsm_user_cb, NULL); OSMO_ASSERT(fi); /* activate reset, then power up */ card_uart_ctrl(&g_cuart, CUART_CTL_RST, true); card_uart_ctrl(&g_cuart, CUART_CTL_POWER_1V8, true); osmo_fsm_inst_dispatch(fi, ISO7816_E_POWER_UP_IND, NULL); /* activate clock */ card_uart_ctrl(&g_cuart, CUART_CTL_CLOCK, true); /* wait some time and release reset */ usleep(10000); card_uart_ctrl(&g_cuart, CUART_CTL_RST, false); osmo_fsm_inst_dispatch(fi, ISO7816_E_RESET_REL_IND, NULL); /* process any events in polling mode for initial change */ osmo_select_main(1); struct msgb *apdu; while (1) { /* check if the new state requires us to do something */ switch (g_tstate) { case ST_ATR_DONE: apdu = msgb_alloc(512, "TPDU"); msgb_put_u8(apdu, 0x00); msgb_put_u8(apdu, 0xa4); msgb_put_u8(apdu, 0x00); msgb_put_u8(apdu, 0x04); msgb_put_u8(apdu, 0x02); msgb_put_u8(apdu, 0x2f); msgb_put_u8(apdu, 0x00); osmo_fsm_inst_dispatch(fi, ISO7816_E_XCEIVE_TPDU_CMD, apdu); g_tstate = ST_IN_TPDU; break; default: break; } osmo_select_main(0); } exit(0); }