FreeCalypso > hg > freecalypso-tools
view target-utils/simagent/exchange.c @ 921:74d284add54d
fc-fsio: guard against bogus readdir results from the target
If the FFS being operated on contains SE K2x0 extended filenames,
readdir will return strings that are bad for printing. We need to
guard against this possibility, and also against possible other
bogosity that could be sent by other alien firmwares.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 31 Dec 2022 22:55:23 +0000 |
parents | 56506e9165bc |
children |
line wrap: on
line source
/* * 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; { int rc; unsigned null_count, bytes_rcvd, ack, ack1; u8 data[256]; if (!datalen) datalen = 256; ack = ins & 0xFE; ack1 = ~ins & 0xFE; bytes_rcvd = 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, data, bytes_rcvd); return; } if ((rc & 0xFE) == ack) { if (bytes_rcvd >= datalen) { bad_xfer_req: printf( "ERROR: SIM requests more xfer after we received all expected data\n"); return; } while (bytes_rcvd < datalen) { rc = rx_sim_byte_hl(); if (rc < 0) return; data[bytes_rcvd++] = rc; } continue; } if ((rc & 0xFE) == ack1) { if (bytes_rcvd >= datalen) goto bad_xfer_req; rc = rx_sim_byte_hl(); if (rc < 0) return; data[bytes_rcvd++] = rc; continue; } printf("ERROR: non-understood procedure byte %02X\n", rc); return; } } void cmd_exchange(argstr) char *argstr; { u8 cmd[260]; unsigned count; 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; count = rc; if (count < 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 (count > 5) exchange_data_out(cmd[1], cmd + 5, count - 5); else exchange_data_in(cmd[1], cmd[4]); }