From 8bd3d51b23e328e91c209dbebe8cfe002b0b0042 Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 12 Sep 2006 17:37:00 +0000 Subject: move to new directory git-svn-id: https://svn.openpcd.org:2342/trunk@193 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- host/opcd_sh.c | 495 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 host/opcd_sh.c (limited to 'host/opcd_sh.c') diff --git a/host/opcd_sh.c b/host/opcd_sh.c new file mode 100644 index 0000000..c9b38b4 --- /dev/null +++ b/host/opcd_sh.c @@ -0,0 +1,495 @@ +#include +#include +#include +#include +#include + +#include "zebvty/vty.h" +#include "zebvty/command.h" + +#define MAX_BUFFER_SIZE 2048 +#define MAX_LENC MAX_BUFFER_SIZE +#define MAX_LENR MAX_LENC +#define MAX_COMMAND_SIZE 2048 + +static void strcompact(char *str) +{ + int i, j = 0; + + for (i = 0; i < strlen(str); i++) { + if (!isspace(str[i])) + str[j++] = tolower(str[i]); + } + str[j] = 0; +} + +static int strtobin(char *s, unsigned char *d, unsigned int *len) +{ + long l; + int i, ret; + + if (*s == ':') + s++; + + for (i = 0; i < (strlen(s) >> 1); i++) { + if (i >= MAX_LENC || i >> *len) + return 0; + ret = sscanf(s + (i << 1), "%2lx", &l); + if (ret != 1) + return 0; + d[i] = l & 0xff; + } + *len = i; + + return 1; +} + +DEFUN(rc632_reg_read, + rc632_reg_read_cmd, + "reg_read WORD", + "Read register of RC632\n") +{ +#if 0 + if (send_hex_command(vty, argv[0]) < 0) + return CMD_ERR_NO_MATCH; +#endif + return CMD_SUCCESS; +} + + +#if 0 +static int select_file(struct vty *v, int absolute, int path, + char *selector, unsigned int sellen, + unsigned char *rsp, unsigned int *rlen) +{ + unsigned char cmd[MAX_LENC]; + + cmd[0] = 0x00; + cmd[1] = 0xa4; + if (absolute) { + if (path) + cmd[2] = 0x08; + else + cmd[2] = 0x00; + } else { + if (path) + cmd[2] = 0x09; + else + cmd[2] = 0x02; + } + cmd[3] = 0x00; // FIXME: other templates + + cmd[4] = sellen & 0xff; + + memcpy(cmd[5], selector, sellen); + cmd[5+sellen] = 0x00; + + send_apdu(hCard, v, cmd, 5+cmd[4], rsp, rlen); + parse_selectfile_response(hCard, v, rsp, *rlen); + return CMD_SUCCESS; + +} + +DEFUN(send_7816_select_file_absolute_fid, + send_7816_select_file_absolute_fid_cmd, + "select file absolute fid WORD", + "Selects a file on the ICC\n") +{ + char *file = argv[0]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr = MAX_LENR; + unsigned char selector[255]; + unsigned int sellen = 255; + + if (strtobin(file, selector, &sellen) < 0) + return CMD_ERR_NO_MATCH; + + return select_file(vty, 1, 0, selector, sellen, rsp, &lenr); +} + +DEFUN(send_7816_select_file_absolute_path, + send_7816_select_file_absolute_path_cmd, + "select file absolute path WORD", + "Selects a file on the ICC\n") +{ + char *file = argv[0]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr = MAX_LENR; + unsigned char selector[255]; + unsigned int sellen = 255; + + if (strtobin(file, selector, &sellen) < 0) + return CMD_ERR_NO_MATCH; + + + return select_file(vty, 1, 1, selector, sellen, rsp, &lenr); +} + +DEFUN(send_7816_select_file_relative_fid, + send_7816_select_file_relative_fid_cmd, + "select file absolute fid WORD", + "Selects a file on the ICC\n") +{ + char *file = argv[0]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr = MAX_LENR; + unsigned char selector[255]; + unsigned int sellen = 255; + + if (strtobin(file, selector, &sellen) < 0) + return CMD_ERR_NO_MATCH; + + + return select_file(vty, 0, 0, selector, sellen, rsp, &lenr); +} + + +DEFUN(send_7816_select_file_relative_path, + send_7816_select_file_relative_path_cmd, + "select file relative path WORD", + "Selects a file on the ICC\n") +{ + char *file = argv[0]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr = MAX_LENR; + unsigned char selector[255]; + unsigned int sellen = 255; + + if (strtobin(file, selector, &sellen) < 0) + return CMD_ERR_NO_MATCH; + + + return select_file(vty, 0, 1, selector, sellen, rsp, &lenr); +} + +DEFUN(send_7816_select_dir, + send_7816_select_dir_cmd, + "select directory (MF|PARENT|CHILD) (FID|AID)", + "Selects a directory on the ICC\n") +{ + char *file = argv[1]; + char *type = argv[0]; + char cmd[22]; + char rsp[MAX_LENR]; + int len, lenr = MAX_LENR; + int empty = 0; + + if (!type) + return CMD_ERR_NO_MATCH; + + memset(cmd, 0, sizeof(cmd)); + cmd[1] = 0xa4; + + if (!strcmp(type, "MF")) { + cmd[2] = 0x00; + cmd[3] = 0x00; + cmd[4] = 2; /* length */ + cmd[5] = 0x3f; /* 3ff0 */ + cmd[6] = 0xf0; + empty = 1; + } else if (!strcmp(type, "PARENT")) { + cmd[2] = 0x03; + cmd[3] = 0x00; + cmd[4] = 0x00; + empty = 1; + } else if (!strcmp(file, "CHILD")) { + cmd[2] = 0x01; + cmd[3] = 0x00; + } else { + cmd[2] = 0x00; + cmd[3] = 0x00; + } + + if (!empty) { + len = 16; + /* convert hex string of identifier to bytecode */ + strtobin(file, &cmd[5], &len); + cmd[4] = len & 0xff; + } + send_apdu(hCard, vty, cmd, 5+cmd[4], rsp, &lenr); + parse_selectfile_response(hCard, vty, rsp, lenr); + return CMD_SUCCESS; +} + +DEFUN(send_7816_ls, + send_7816_ls_cmd, + "ls", + "Tries to list all files on a 7816-4 compliant ICC\n") +{ + return CMD_SUCCESS; +} + +DEFUN(send_7816_tree, + send_7816_tree_cmd, + "tree", + "Tries to list a full DF hiararchy tree on a 7816-4 compliant ICC\n") +{ + + return CMD_SUCCESS; +} + +DEFUN(send_7816_read_binary, + send_7816_read_binary_cmd, + "read binary OFFSET LENGTH", + "Read bytes form a previously selected EF\n") +{ + unsigned char cmd[] = { 0x00, 0xb0, 0x00, 0x00, 0x00 }; + unsigned char rsp[MAX_LENR]; // FIXME + unsigned int lenr = MAX_LENR; + + unsigned long datalen; + unsigned long offset; + + offset = strtoul(argv[0], NULL, 0); + if (offset == ULONG_MAX || offset > 0xffff) + return CMD_ERR_NO_MATCH; + + datalen = strtoul(argv[1], NULL, 0); + if (datalen == ULONG_MAX || datalen > 0xff) + return CMD_ERR_NO_MATCH; + + cmd[2] = (offset >> 8) & 0xff; + cmd[3] = offset & 0xff; + cmd[4] = datalen & 0xff; + + send_apdu(hCard, vty, cmd, 5+cmd[4], rsp, &lenr); + if (lenr < 2) + return CMD_SUCCESS; // FIXME + + parse_sw(vty, rsp[lenr-2], rsp[lenr-1]); + + return CMD_SUCCESS; +} + +DEFUN(send_7816_write_binary, + send_7816_write_binary_cmd, + "write binary OFFSET LENGTH DATA", + "Write bytes to a previously selected EF\n") +{ + unsigned char cmd[MAX_LENC]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr; + + unsigned long datalen; + unsigned long offset; + + offset = strtoul(argv[0], NULL, 0); + if (offset == ULONG_MAX || offset > 0xffff) + return CMD_ERR_NO_MATCH; + + datalen = strtoul(argv[1], NULL, 0); + if (datalen == ULONG_MAX || datalen > 0xff) + return CMD_ERR_NO_MATCH; + + memset(cmd, 0, sizeof(cmd)); + + cmd[1] = 0xd0; + cmd[2] = (offset >> 8) & 0xff; + cmd[3] = offset & 0xff; + + if (!strtobin(argv[2], cmd+5, &datalen)) { + vty_out(vty, "command decoding error%s", vty_newline(vty)); + return -1; + } + + cmd[4] = datalen & 0xff; + + send_apdu(hCard, vty, cmd, 5+cmd[4], rsp, &lenr); + if (lenr < 2) + return CMD_SUCCESS; // FIXME + + parse_sw(vty, rsp[lenr-2], rsp[lenr-1]); + + return CMD_SUCCESS; + + return CMD_SUCCESS; +} + +DEFUN(send_7816_update_binary, + send_7816_update_binary_cmd, + "update binary OFFSET LENGTH DATA", + "Update bytes of a previously selected EF\n") +{ + unsigned char cmd[MAX_LENC]; + unsigned char rsp[MAX_LENR]; + unsigned int lenr; + + unsigned long datalen; + unsigned long offset; + + offset = strtoul(argv[0], NULL, 0); + if (offset == ULONG_MAX || offset > 0xffff) + return CMD_ERR_NO_MATCH; + + datalen = strtoul(argv[1], NULL, 0); + if (datalen == ULONG_MAX || datalen > 0xff) + return CMD_ERR_NO_MATCH; + + memset(cmd, 0, sizeof(cmd)); + + cmd[1] = 0xd6; + cmd[2] = (offset >> 8) & 0xff; + cmd[3] = offset & 0xff; + + if (!strtobin(argv[2], cmd+5, &datalen)) { + vty_out(vty, "command decoding error%s", vty_newline(vty)); + return -1; + } + + cmd[4] = datalen & 0xff; + + send_apdu(hCard, vty, cmd, 5+cmd[4], rsp, &lenr); + if (lenr < 2) + return CMD_SUCCESS; // FIXME + + parse_sw(vty, rsp[lenr-2], rsp[lenr-1]); + + return CMD_SUCCESS; +} + +DEFUN(send_7816_erase_binary, + send_7816_erase_binary_cmd, + "erase binary OFFSET LENGTH", + "Erase bytes of a previously selected EF\n") +{ + unsigned char cmd[8] = { 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + unsigned char rsp[MAX_LENR]; + unsigned int lenr; + + unsigned long datalen; + unsigned long offset; + + offset = strtoul(argv[0], NULL, 0); + if (offset == ULONG_MAX || offset > 0xffff) + return CMD_ERR_NO_MATCH; + + datalen = strtoul(argv[1], NULL, 0); + if (datalen == ULONG_MAX || (offset+datalen > 0xffff)) + return CMD_ERR_NO_MATCH; + + cmd[2] = (offset >> 8) & 0xff; + cmd[3] = offset & 0xff; + cmd[4] = 0x02; + cmd[5] = ((offset+datalen) >> 8) & 0xff; + cmd[6] = (offset+datalen) & 0xff; + + send_apdu(hCard, vty, cmd, 5+cmd[4], rsp, &lenr); + if (lenr < 2) + return CMD_SUCCESS; // FIXME + + parse_sw(vty, rsp[lenr-2], rsp[lenr-1]); + + return CMD_SUCCESS; +} + +DEFUN(send_7816_get_response, + send_7816_get_response_cmd, + "get response LENGTH", + "Get more data from the ICC\n") +{ + unsigned char cmd[6] = { 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00 }; + unsigned char rsp[MAX_LENR]; + unsigned int lenr = MAX_LENR; + + unsigned long length; + + length = strtoul(argv[0], NULL, 0); + if (length == ULONG_MAX || length > 0xff) + return CMD_ERR_NO_MATCH; + + cmd[5] = length & 0xff; + + send_apdu(hCard, vty, cmd, 6, rsp, &lenr); + if (lenr < 2) + return CMD_SUCCESS; // FIXME + + parse_sw(vty, rsp[lenr-2], rsp[lenr-1]); + + return CMD_SUCCESS; + +} +#endif + +DEFUN(rc632, + rc632_cmd, + "rc632", "Commands related to low-level RC632 access\n") +{ + vty->node = RC632_NODE; + return CMD_SUCCESS; +} + +/* dummy */ +static int send_config_write(struct vty *v) +{ + return CMD_SUCCESS; +} + +struct cmd_node rc632_node = { + RC632_NODE, + "%s(rc632)# ", + 1, +}; + +static int opcdshell_init() +{ + cmd_init(1); + vty_init(); + + install_node(&rc632_node, send_config_write); + + install_element(RC632_NODE, &rc632_reg_read_cmd); + +#if 0 + install_element(RC632_NODE, &send_7816_select_file_absolute_fid_cmd); + install_element(RC632_NODE, &send_7816_select_file_absolute_path_cmd); + install_element(RC632_NODE, &send_7816_select_file_relative_fid_cmd); + install_element(RC632_NODE, &send_7816_select_file_relative_path_cmd); + + install_element(RC632_NODE, &send_7816_select_dir_cmd); + install_element(RC632_NODE, &send_7816_ls_cmd); + install_element(RC632_NODE, &send_7816_tree_cmd); + + install_element(RC632_NODE, &send_7816_read_binary_cmd); + install_element(RC632_NODE, &send_7816_write_binary_cmd); + install_element(RC632_NODE, &send_7816_update_binary_cmd); + install_element(RC632_NODE, &send_7816_erase_binary_cmd); + + install_element(RC632_NODE, &send_7816_get_response_cmd); +#endif + + install_default(RC632_NODE); + + install_element(VIEW_NODE, &rc632_cmd); + + return 0; +} + +static int opcdshell(void) +{ + struct vty *v; + + v = vty_create(0); + if (!v) + return -1; + while (1) { + vty_read(v); + } + return 0; +} + + +/*********************************************************************** + * main program, copied from pcsc-lite 'testpcsc.c' + ***********************************************************************/ + +int main(int argc, char **argv) +{ + opcdshell_init(); + + printf("\nopcd_shell (C) 2006 Harald Welte \n\n"); + + opcdshell(); + + return 0; +} -- cgit v1.2.3