# HG changeset patch # User Mychaela Falconia # Date 1615673168 0 # Node ID c136a1a2474b56da155372e4a092906c4065fd55 # Parent badc5399d64114c5d88f5f00536f8964f655e798 simagent: initial implementation of APDU exchange diff -r badc5399d641 -r c136a1a2474b target-utils/simagent/Makefile --- a/target-utils/simagent/Makefile Sat Mar 13 21:39:34 2021 +0000 +++ b/target-utils/simagent/Makefile Sat Mar 13 22:06:08 2021 +0000 @@ -7,8 +7,8 @@ INSTDIR=/opt/freecalypso/target-bin PROG= simagent -OBJS= crt0.o byterx.o cmdtab.o invtable.o main.o simup.o spenh.o stringarg.o \ - tx.o +OBJS= crt0.o byterx.o cmdtab.o exchange.o invtable.o main.o simup.o spenh.o \ + stringarg.o tx.o LIBS= ../libcommon/libcommon.a ../libprintf/libprintf.a ../libbase/libbase.a \ ../libc/libc.a LIBGCC= `${CC} -print-file-name=libgcc.a` diff -r badc5399d641 -r c136a1a2474b target-utils/simagent/byterx.c --- a/target-utils/simagent/byterx.c Sat Mar 13 21:39:34 2021 +0000 +++ b/target-utils/simagent/byterx.c Sat Mar 13 22:06:08 2021 +0000 @@ -1,6 +1,7 @@ #include #include "types.h" #include "simregs.h" +#include "timeout.h" rx_sim_byte(count) unsigned count; @@ -12,6 +13,24 @@ return(-1); } +rx_sim_byte_hl() +{ + int rc; + unsigned parcnt; + + for (parcnt = 0; parcnt < 3; parcnt++) { + rc = rx_sim_byte(SIM_WAIT_TIMEOUT); + if (rc < 0) { + printf("ERROR: timeout waiting for SIM response\n"); + return(-1); + } + if (rc & 0x100) + return rc & 0xFF; + } + printf("ERROR: received bad parity 3 times in a row\n"); + return(-1); +} + flush_rx_fifo() { unsigned count; diff -r badc5399d641 -r c136a1a2474b target-utils/simagent/cmdtab.c --- a/target-utils/simagent/cmdtab.c Sat Mar 13 21:39:34 2021 +0000 +++ b/target-utils/simagent/cmdtab.c Sat Mar 13 22:06:08 2021 +0000 @@ -3,6 +3,7 @@ extern void cmd_abbr(); extern void cmd_abbw(); extern void cmd_baud_switch(); +extern void cmd_exchange(); extern void cmd_jump(); extern void cmd_r8(); extern void cmd_r16(); @@ -21,6 +22,7 @@ extern void print_atr(); const struct cmdtab cmdtab[] = { + {"X", cmd_exchange}, {"abbinit", abb_init}, {"abbpage2", abb_unlock_page2}, {"abbr", cmd_abbr}, diff -r badc5399d641 -r c136a1a2474b target-utils/simagent/exchange.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/target-utils/simagent/exchange.c Sat Mar 13 22:06:08 2021 +0000 @@ -0,0 +1,118 @@ +/* + * This module implements our main function: exchange of command + * and response APDUs. + */ + +#include "types.h" + +extern int sim_if_state; + +static void +finish_sw(sw1, data, datalen) + unsigned sw1, datalen; + u8 *data; +{ + unsigned sw2, n; + int rc; + + rc = rx_sim_byte_hl(); + if (rc < 0) + return; + sw2 = rc; + for (n = 0; n < datalen; n++) + printf("%02X", data[n]); + printf("%02X%02X\n", sw1, sw2); +} + +static void +exchange_data_out(ins, data, datalen) + unsigned ins, datalen; + u8 *data; +{ + int rc; + unsigned null_count, bytes_sent, ack, ack1; + + ack = ins & 0xFE; + ack1 = ~ins & 0xFE; + bytes_sent = 0; + null_count = 0; + for (;;) { + rc = rx_sim_byte_hl(); + if (rc < 0) + return; + if (rc == 0x60) { + null_count++; + if (null_count >= 32) { + printf( + "ERROR: too many stalling NULL bytes received from SIM\n"); + return; + } + continue; + } + if ((rc & 0xF0) == 0x60 || (rc & 0xF0) == 0x90) { + finish_sw(rc, 0, 0); + return; + } + if ((rc & 0xFE) == ack) { + if (bytes_sent >= datalen) { +bad_xfer_req: printf( + "ERROR: SIM requests more xfer after we sent everything\n"); + return; + } + rc = send_to_sim(data + bytes_sent, + datalen - bytes_sent); + if (rc < 0) + return; + bytes_sent = datalen; + continue; + } + if ((rc & 0xFE) == ack1) { + if (bytes_sent >= datalen) + goto bad_xfer_req; + rc = send_to_sim(data + bytes_sent, 1); + if (rc < 0) + return; + bytes_sent++; + continue; + } + printf("ERROR: non-understood procedure byte %02X\n", rc); + return; + } +} + +static void +exchange_data_in(ins, datalen) + unsigned ins, datalen; +{ + printf("ERROR: data in mode not implemented yet\n"); +} + +void +cmd_exchange(argstr) + char *argstr; +{ + u8 cmd[260]; + int rc; + + if (sim_if_state != 2) { + printf("ERROR: SIM interface is not up\n"); + return; + } + rc = decode_hex_string_arg(argstr, cmd, 260); + if (rc < 0) + return; + if (rc < 5) { + printf("ERROR: command APDU is shorter than 5 bytes\n"); + return; + } + rc = flush_rx_fifo(); + if (rc < 0) + return; + rc = send_to_sim(cmd, 5); + if (rc < 0) + return; + if (rc > 5) + exchange_data_out(cmd[1], cmd + 5, rc - 5); + else + exchange_data_in(cmd[1], cmd[4]); +}