# HG changeset patch # User Mychaela Falconia # Date 1611537834 0 # Node ID fa7005185b8408d38e152023293a81cc60b385e0 # Parent 2e35070d289f3fc37e7b49bcdfe45a092e47d444 fc-simtool: restore-file command implemented diff -r 2e35070d289f -r fa7005185b84 simtool/Makefile --- a/simtool/Makefile Mon Jan 25 00:14:19 2021 +0000 +++ b/simtool/Makefile Mon Jan 25 01:23:54 2021 +0000 @@ -2,7 +2,8 @@ CFLAGS= -O2 -I/usr/include/PCSC PROG= fc-simtool OBJS= apdu.o atr.o cardconnect.o dispatch.o globals.o hexdump.o hlread.o \ - main.o names.o readcmd.o readops.o saverestore.o select.o telsum.o + main.o names.o readcmd.o readops.o saverestore.o select.o telsum.o \ + writeops.o all: ${PROG} diff -r 2e35070d289f -r fa7005185b84 simtool/dispatch.c --- a/simtool/dispatch.c Mon Jan 25 00:14:19 2021 +0000 +++ b/simtool/dispatch.c Mon Jan 25 01:23:54 2021 +0000 @@ -17,6 +17,7 @@ extern int cmd_readbin(); extern int cmd_readef(); extern int cmd_readrec(); +extern int cmd_restore_file(); extern int cmd_savebin(); extern int cmd_select(); extern int cmd_telecom_sum(); @@ -43,6 +44,7 @@ {"readbin", 2, 2, cmd_readbin}, {"readef", 1, 1, cmd_readef}, {"readrec", 1, 2, cmd_readrec}, + {"restore-file", 2, 2, cmd_restore_file}, {"savebin", 2, 2, cmd_savebin}, {"select", 1, 1, cmd_select}, {"sim-resp", 0, 0, display_sim_resp_in_hex}, diff -r 2e35070d289f -r fa7005185b84 simtool/saverestore.c --- a/simtool/saverestore.c Mon Jan 25 00:14:19 2021 +0000 +++ b/simtool/saverestore.c Mon Jan 25 01:23:54 2021 +0000 @@ -4,8 +4,11 @@ */ #include +#include +#include #include #include +#include #include #include #include "globals.h" @@ -87,3 +90,109 @@ fclose(of); return(rc); } + +static +restore_transparent(data) + u_char *data; +{ + unsigned off, cc; + int rc; + + for (off = 0; off < curfile_total_size; off += cc) { + cc = curfile_total_size - off; + if (cc > 255) + cc = 255; + rc = update_bin_op(off, data + off, cc); + if (rc < 0) + return(rc); + } + return(0); +} + +static +restore_records(data) + u_char *data; +{ + unsigned recno; + u_char *dp; + int rc; + + dp = data; + for (recno = 1; recno <= curfile_record_count; recno++) { + rc = update_rec_op(recno, 0x04, dp, curfile_record_len); + if (rc < 0) + return(rc); + dp += curfile_record_len; + } + return(0); +} + +cmd_restore_file(argc, argv) + char **argv; +{ + int file_id, rc, fd; + struct stat st; + u_char *databuf; + + if (isxdigit(argv[1][0]) && isxdigit(argv[1][1]) && + isxdigit(argv[1][2]) && isxdigit(argv[1][3]) && !argv[1][4]) + file_id = strtoul(argv[1], 0, 16); + else + file_id = find_symbolic_file_name(argv[1]); + if (file_id < 0) { + fprintf(stderr, +"error: file ID argument is not a hex value or a recognized symbolic name\n"); + return(-1); + } + rc = select_op(file_id); + if (rc < 0) + return(rc); + rc = parse_ef_select_response(); + if (rc < 0) + return(rc); + if (!curfile_total_size) { + printf("SIM indicates file of zero length, nothing to do\n"); + return(0); + } + fd = open(argv[2], O_RDONLY); + if (fd < 0) { + perror(argv[2]); + return(-1); + } + fstat(fd, &st); + if ((st.st_mode & S_IFMT) != S_IFREG) { + fprintf(stderr, "error: %s is not a regular file\n", argv[2]); + close(fd); + return(-1); + } + if (st.st_size != curfile_total_size) { + fprintf(stderr, + "error: length of %s does not match SIM EF length of %u bytes\n", + argv[2], curfile_total_size); + close(fd); + return(-1); + } + databuf = malloc(curfile_total_size); + if (!databuf) { + perror("malloc for file data"); + close(fd); + return(-1); + } + read(fd, databuf, curfile_total_size); + close(fd); + switch (curfile_structure) { + case 0x00: + /* transparent */ + rc = restore_transparent(databuf); + break; + case 0x01: + /* record-based */ + rc = restore_records(databuf); + break; + case 0x03: + fprintf(stderr, "error: cyclic files are not supported\n"); + rc = -1; + } + free(databuf); + return(rc); +} diff -r 2e35070d289f -r fa7005185b84 simtool/writeops.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simtool/writeops.c Mon Jan 25 01:23:54 2021 +0000 @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +update_bin_op(offset, data, len) + unsigned offset, len; + u_char *data; +{ + u_char cmd[260]; + int rc; + + /* UPDATE BINARY command APDU */ + cmd[0] = 0xA0; + cmd[1] = 0xD6; + cmd[2] = offset >> 8; + cmd[3] = offset; + cmd[4] = len; + bcopy(data, cmd + 5, len); + rc = apdu_exchange(cmd, len + 5); + if (rc < 0) + return(rc); + if (sim_resp_sw != 0x9000) { + fprintf(stderr, "bad SW response to UPDATE BINARY: %04X\n", + sim_resp_sw); + return(-1); + } + return(0); +} + +update_rec_op(recno, mode, data, len) + unsigned recno, mode, len; + u_char *data; +{ + u_char cmd[260]; + int rc; + + /* UPDATE RECORD command APDU */ + cmd[0] = 0xA0; + cmd[1] = 0xDC; + cmd[2] = recno; + cmd[3] = mode; + cmd[4] = len; + bcopy(data, cmd + 5, len); + rc = apdu_exchange(cmd, len + 5); + if (rc < 0) + return(rc); + if (sim_resp_sw != 0x9000) { + fprintf(stderr, "bad SW response to UPDATE RECORD: %04X\n", + sim_resp_sw); + return(-1); + } + return(0); +}