From 269df3a6daaa13051383704a3c020b0bd29935d2 Mon Sep 17 00:00:00 2001 From: jey Date: Wed, 9 Jan 2002 01:03:10 +0000 Subject: [PATCH] - created opensc-explorer tool - increased support for CryptoFlex cards git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@152 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/card-multiflex.c | 52 +++- src/libopensc/card.c | 19 +- src/libopensc/iso7816.c | 25 +- src/libopensc/log.c | 49 ++-- src/libopensc/opensc.h | 8 +- src/tools/Makefile.am | 4 +- src/tools/opensc-explorer.c | 445 +++++++++++++++++++++++++++++++++ src/tools/opensc-tool.c | 39 +-- src/tools/util.c | 33 ++- src/tools/util.h | 3 +- 10 files changed, 605 insertions(+), 72 deletions(-) create mode 100644 src/tools/opensc-explorer.c diff --git a/src/libopensc/card-multiflex.c b/src/libopensc/card-multiflex.c index 41dff9bd..6bac45c4 100644 --- a/src/libopensc/card-multiflex.c +++ b/src/libopensc/card-multiflex.c @@ -165,9 +165,10 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path, { int r, i; struct sc_apdu apdu; - u8 rbuf[MAX_BUFFER_SIZE]; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; const u8 *pathptr = path->value; size_t pathlen = path->len; + int locked = 0; SC_FUNC_CALLED(card->ctx, 3); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0); @@ -182,15 +183,22 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path, if (pathlen != 2 || memcmp(pathptr, "\x3F\x00", 2) != 0) { struct sc_path tmppath; + locked = 1; + r = sc_lock(card); + SC_TEST_RET(card->ctx, r, "sc_lock() failed"); if (memcmp(pathptr, "\x3F\x00", 2) != 0) { sc_format_path("I3F00", &tmppath); r = mflex_select_file(card, &tmppath, NULL); + if (r) + sc_unlock(card); SC_TEST_RET(card->ctx, r, "Unable to select Master File (MF)"); } while (pathlen > 2) { memcpy(tmppath.value, pathptr, 2); tmppath.len = 2; r = mflex_select_file(card, &tmppath, NULL); + if (r) + sc_unlock(card); SC_TEST_RET(card->ctx, r, "Unable to select DF"); pathptr += 2; pathlen -= 2; @@ -211,13 +219,21 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path, /* No need to get file information, if file is NULL or already * valid. */ +#if 0 if (file == NULL || sc_file_valid(file)) +#endif + if (file == NULL) apdu.resplen = 0; r = sc_transmit_apdu(card, &apdu); + if (locked) + sc_unlock(card); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); SC_TEST_RET(card->ctx, r, "Card returned error"); +#if 0 if (file == NULL || sc_file_valid(file)) +#endif + if (file == NULL) return 0; if (apdu.resplen < 14) @@ -235,6 +251,39 @@ static int mflex_select_file(struct sc_card *card, const struct sc_path *path, return parse_flex_sf_reply(card->ctx, apdu.resp, apdu.resplen, file); } +static int mflex_list_files(struct sc_card *card, u8 *buf, size_t buflen) +{ + struct sc_apdu apdu; + u8 rbuf[4]; + int r; + size_t count = 0; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA8, 0, 0); + apdu.cla = 0xF0; + apdu.le = 4; + apdu.resplen = 4; + apdu.resp = rbuf; + while (buflen > 2) { + r = sc_transmit_apdu(card, &apdu); + if (r) + return r; + if (apdu.sw1 == 0x6A && apdu.sw2 == 0x82) + break; + r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); + if (r) + return r; + if (apdu.resplen != 4) { + error(card->ctx, "expected 4 bytes, got %d.\n", apdu.resplen); + return SC_ERROR_ILLEGAL_RESPONSE; + } + memcpy(buf, rbuf + 2, 2); + buf += 2; + count += 2; + buflen -= 2; + } + return count; +} + static const struct sc_card_driver * sc_get_driver(void) { const struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); @@ -244,6 +293,7 @@ static const struct sc_card_driver * sc_get_driver(void) mflex_ops.init = mflex_init; mflex_ops.finish = mflex_finish; mflex_ops.select_file = mflex_select_file; + mflex_ops.list_files = mflex_list_files; return &mflex_drv; } diff --git a/src/libopensc/card.c b/src/libopensc/card.c index c16dc52a..5af5c9ea 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -506,21 +506,16 @@ int sc_unlock(struct sc_card *card) SC_FUNC_RETURN(card->ctx, 2, r); } -int sc_list_files(struct sc_card *card, u8 *buf, int buflen) +int sc_list_files(struct sc_card *card, u8 *buf, size_t buflen) { - struct sc_apdu apdu; int r; - SC_FUNC_CALLED(card->ctx, 2); - sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0); - apdu.resp = buf; - apdu.resplen = buflen; - apdu.le = 0; - r = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (apdu.resplen == 0) - return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); - return apdu.resplen; + assert(card != NULL); + SC_FUNC_CALLED(card->ctx, 1); + if (card->ops->list_files == NULL) + SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_NOT_SUPPORTED); + r = card->ops->list_files(card, buf, buflen); + SC_FUNC_RETURN(card->ctx, 1, r); } int sc_create_file(struct sc_card *card, const struct sc_file *file) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 0d47b7b9..b5a8eee9 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -277,11 +277,17 @@ static int iso7816_select_file(struct sc_card *card, memcpy(&file->path.value, path, pathlen); file->path.len = pathlen; } +#if 0 if (file == NULL || sc_file_valid(file)) +#endif + if (file == NULL) apdu.resplen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (file == NULL || sc_file_valid(file)) { +#if 0 + if (file == NULL || sc_file_valid(file)) +#endif + if (file == NULL) { if (apdu.sw1 == 0x61) SC_FUNC_RETURN(card->ctx, 2, 0); SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2)); @@ -421,6 +427,22 @@ static int iso7816_delete_file(struct sc_card *card, const struct sc_path *path) return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); } +static int iso7816_list_files(struct sc_card *card, u8 *buf, size_t buflen) +{ + struct sc_apdu apdu; + int r; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0); + apdu.resp = buf; + apdu.resplen = buflen; + apdu.le = 0; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + if (apdu.resplen == 0) + return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2); + return apdu.resplen; +} + static struct sc_card_operations iso_ops = { NULL, }; @@ -449,6 +471,7 @@ const struct sc_card_driver * sc_get_iso7816_driver(void) iso_ops.get_challenge = iso7816_get_challenge; iso_ops.create_file = iso7816_create_file; iso_ops.delete_file = iso7816_delete_file; + iso_ops.list_files = iso7816_list_files; } return &iso_driver; } diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 4c458f42..3dac0f11 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -58,14 +58,39 @@ void do_log(struct sc_context *ctx, int facility, const char *file, va_end(ap); } +int use_color(struct sc_context *ctx, FILE *outf) +{ + static char *term = NULL; + static const char *terms[] = { "linux", "xterm", "Eterm" }; + int term_count = sizeof(terms)/sizeof(terms[0]); + int do_color = 0; + int i; + + if (!ctx->use_std_output) + return 0; + if (term == NULL) { + term = getenv("TERM"); + if (term == NULL) + return 0; + } + do_color = 0; + for (i = 0; i < term_count; i++) + if (strcmp(terms[i], term) == 0) { + do_color = 1; + break; + } + if (!do_color) + return 0; + if (!isatty(fileno(outf))) + return 0; + return do_color; +} + void do_log2(struct sc_context *ctx, int type, const char *file, int line, const char *func, const char *format, va_list args) { FILE *outf = NULL; char buf[1024], *p; - static char *term = NULL; - const char *terms[] = { "linux", "xterm", "Eterm" }; - int term_count = sizeof(terms)/sizeof(terms[0]); int left, r; struct timeval tv; @@ -96,23 +121,7 @@ void do_log2(struct sc_context *ctx, int type, const char *file, return; if (ctx->use_std_output) { const char *color_pfx = "", *color_sfx = ""; - int do_color = 0; - int i; - if (term == NULL) - term = getenv("TERM"); - if (term != NULL) - do_color = 1; - if (do_color) { - do_color = 0; - for (i = 0; i < term_count; i++) - if (strcmp(terms[i], term) == 0) { - do_color = 1; - break; - } - } - if (do_color && !isatty(fileno(outf))) - do_color = 0; - if (do_color) { + if (use_color(ctx, outf)) { color_sfx = "\33[0m"; switch (type) { case SC_LOG_TYPE_ERROR: diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 18cb7136..99f5b7e0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -293,7 +293,7 @@ struct sc_card_operations { int (*decipher)(struct sc_card *card, const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen); /* compute_signature: Generates a digital signature on the card. Similiar - * to the function decipher. */ + * to the function decipher. */ int (*compute_signature)(struct sc_card *card, const u8 * data, size_t data_len, u8 * out, size_t outlen); int (*change_reference_data)(struct sc_card *card, int ref_qualifier, @@ -308,6 +308,10 @@ struct sc_card_operations { */ int (*create_file)(struct sc_card *card, const struct sc_file *file); int (*delete_file)(struct sc_card *card, const struct sc_path *path); + /* list_files: Enumerates all the files in the current DF, and + * writes the corresponding file identifiers to . Returns + * the number of bytes stored. */ + int (*list_files)(struct sc_card *card, u8 *buf, size_t buflen); }; struct sc_card_driver { @@ -411,7 +415,7 @@ void sc_format_path(const char *path_in, struct sc_path *path_out); int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen); /* Possibly only valid on Setec cards */ -int sc_list_files(struct sc_card *card, u8 * buf, int buflen); +int sc_list_files(struct sc_card *card, u8 * buf, size_t buflen); const char *sc_strerror(int error); diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 6e5fe837..5676a13d 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -3,10 +3,12 @@ INCLUDES = @CFLAGS_PCSC@ @CFLAGS_OPENSC@ LDFLAGS = @LDFLAGS@ @LIBOPENSC@ -bin_PROGRAMS = opensc-tool pkcs15-crypt pkcs15-tool +bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-crypt pkcs15-tool opensc_tool_SOURCES = opensc-tool.c util.c opensc_tool_LDADD = @GETOPTSRC@ +opensc_explorer_SOURCES = opensc-explorer.c util.c +opensc_explorer_LDADD = @GETOPTSRC@ pkcs15_tool_SOURCES = pkcs15-tool.c util.c pkcs15_tool_LDADD = @GETOPTSRC@ pkcs15_crypt_SOURCES = pkcs15-crypt.c util.c diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c new file mode 100644 index 00000000..7f39de00 --- /dev/null +++ b/src/tools/opensc-explorer.c @@ -0,0 +1,445 @@ +/* + * opensc-explorer.c: A shell for accessing SmartCards with libopensc + * + * Copyright (C) 2001 Juha Yrjölä + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "util.h" + +struct sc_context *ctx = NULL; +struct sc_card *card = NULL; +struct sc_file current_file; +struct sc_path current_path; + +const struct option options[] = { { NULL } }; +const char *option_help[] = { NULL }; + +const char *cmds[] = { + "ls", "cd", "debug", "cat", "info" +}; +const int nr_cmds = sizeof(cmds)/sizeof(cmds[0]); + +int die(int ret) +{ + if (card) { + sc_unlock(card); + sc_disconnect_card(card); + } + if (ctx) + sc_destroy_context(ctx); + exit(ret); +} + +static int ambiguous_match(const char **table, int nr_entries, const char *cmd) +{ + int matches = 0; + int last_match = 0; + int i; + + for (i = 0; i < nr_entries; i++) { + if (strncasecmp(cmd, table[i], strlen(cmd)) == 0) { + matches++; + last_match = i; + } + } + if (matches > 1) + return -1; + if (matches == 0) + return -2; + return last_match; +} + +void check_ret(int r, int op, const char *err, const struct sc_file *file) +{ + fprintf(stderr, "%s: %s\n", err, sc_strerror(r)); + if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) + fprintf(stderr, "ACL for operation: %s\n", acl_to_str(file->acl[op])); +} + +void print_file(const struct sc_file *file) +{ + const char *st; + + if (file->type == SC_FILE_TYPE_DF) + printf("["); + else + printf(" "); + printf("%02X%02X", file->id >> 8, file->id & 0xFF); + if (file->type == SC_FILE_TYPE_DF) + printf("]"); + else + printf(" "); + switch (file->type) { + case SC_FILE_TYPE_WORKING_EF: + st = "wEF"; + break; + case SC_FILE_TYPE_INTERNAL_EF: + st = "iEF"; + break; + case SC_FILE_TYPE_DF: + st = "DF"; + break; + default: + st = "???"; + break; + } + printf("\t%4s", st); + printf(" %5d", file->size); + if (file->namelen) { + printf("\tName: "); + print_binary(stdout, file->name, file->namelen); + } + printf("\n"); + return; +} + +int do_ls() +{ + u8 buf[256], *cur = buf; + int r, count; + + r = sc_list_files(card, buf, sizeof(buf)); + if (r < 0) { + check_ret(r, SC_AC_OP_LIST_FILES, "unable to receive file listing", ¤t_file); + return -1; + } + count = r; + printf("FileID\tType Size\n"); + while (count >= 2) { + struct sc_path path; + struct sc_file file; + + memcpy(path.value, cur, 2); + path.len = 2; + path.type = SC_PATH_TYPE_FILE_ID; + r = sc_select_file(card, &path, &file); + if (r) { + check_ret(r, SC_AC_OP_SELECT, "unable to select file", ¤t_file); + return -1; + } + cur += 2; + count -= 2; + print_file(&file); + r = sc_select_file(card, ¤t_path, NULL); + if (r) { + printf("unable to select parent DF: %s\n", sc_strerror(r)); + die(1); + } + } + return 0; +} + +int do_cd(const char *arg) +{ + struct sc_path path; + struct sc_file file; + char buf[6]; + int r; + + if (strcmp(arg, "..") == 0) { + if (current_path.len < 4) { + printf("unable to go up, already in MF.\n"); + return -1; + } + path = current_path; + path.len -= 2; + r = sc_select_file(card, &path, ¤t_file); + if (r) { + printf("unable to go up: %s\n", sc_strerror(r)); + return -1; + } + current_path = path; + return 0; + } + + if (strlen(arg) != 4) { + printf("Usage: cd \n"); + return -1; + } + strcpy(buf, "I"); + strcat(buf, arg); + sc_format_path(buf, &path); + if (path.len != 2) { + printf("Usage: cd \n"); + return -1; + } + r = sc_select_file(card, &path, &file); + if (r) { + check_ret(r, SC_AC_OP_SELECT, "unable to select DF", ¤t_file); + return -1; + } + memcpy(current_path.value + current_path.len, path.value, path.len); + current_path.len += path.len; + current_file = file; + + return 0; +} + + +int do_cat(const char *arg) +{ + u8 buf[256]; + int r, error = 0; + size_t count = 0; + unsigned int idx = 0; + struct sc_path path; + struct sc_file file; + int not_current = 1; + + if (strlen(arg) == 0) { + path = current_path; + file = current_file; + not_current = 0; + } else { + if (strlen(arg) != 4) { + printf("Usage: cat [file_id]\n"); + return -1; + } + strcpy(buf, "I"); + strcat(buf, arg); + sc_format_path(buf, &path); + if (path.len != 2) { + printf("Usage: cat [file_id]\n"); + return -1; + } + r = sc_select_file(card, &path, &file); + if (r) { + check_ret(r, SC_AC_OP_SELECT, "unable to select file", ¤t_file); + return -1; + } + } + count = file.size; + while (count) { + int c = count > sizeof(buf) ? sizeof(buf) : count; + + r = sc_read_binary(card, idx, buf, c, 0); + if (r < 0) { + check_ret(r, SC_AC_OP_READ, "read failed", &file); + error = 1; + goto err; + } + if (r != c) { + printf("expecting %d, got only %d bytes.\n", c, r); + error = 1; + goto err; + } + hex_dump_asc(stdout, buf, c, idx); + idx += c; + count -= c; + } +err: + if (not_current) { + r = sc_select_file(card, ¤t_path, NULL); + if (r) { + printf("unable to select parent file: %s\n", sc_strerror(r)); + die(1); + } + } + return -error; +} + +int do_info(const char *arg) +{ + struct sc_file file; + struct sc_path path; + int r, i; + const char *st; + int not_current = 1; + + if (strlen(arg) == 0) { + path = current_path; + file = current_file; + not_current = 0; + } else { + char buf[6]; + struct sc_path tmppath; + + if (strlen(arg) != 4) { + printf("Usage: info [file_id]\n"); + return -1; + } + strcpy(buf, "I"); + strcat(buf, arg); + sc_format_path(buf, &tmppath); + if (tmppath.len != 2) { + printf("Usage: info [file_id]\n"); + return -1; + } + r = sc_select_file(card, &tmppath, &file); + if (r) { + printf("unable to select file: %s\n", sc_strerror(r)); + return -1; + } + path = current_path; + memcpy(path.value + path.len, tmppath.value, 2); + path.len += 2; + } + switch (file.type) { + case SC_FILE_TYPE_WORKING_EF: + case SC_FILE_TYPE_INTERNAL_EF: + st = "Elementary File"; + break; + case SC_FILE_TYPE_DF: + st = "Dedicated File"; + break; + default: + st = "Unknown File"; + break; + } + printf("\n%s ID %04X\n\n", st, file.id); + printf("%-15s", "File path:"); + for (i = 0; i < path.len; i++) { + for (i = 0; i < path.len; i++) { + if ((i & 1) == 0 && i) + printf("/"); + printf("%02X", path.value[i]); + } + } + printf("\n%-15s%d bytes\n", "File size:", file.size); + + if (file.type == SC_FILE_TYPE_DF) { + const char *ops[] = { + "SELECT", "LOCK", "DELETE", "CREATE", "REHABILITATE", + "INVALIDATE", "LIST FILES" + }; + if (file.namelen) { + printf("%-15s", "DF name:"); + print_binary(stdout, file.name, file.namelen); + printf("\n"); + } + for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { + char buf[80]; + + sprintf(buf, "ACL for %s:", ops[i]); + printf("%-25s%s\n", buf, acl_to_str(file.acl[i])); + } + } else { + const char *structs[] = { + "Unknown", "Transparent", "Linear fixed", + "Linear fixed, SIMPLE-TLV", "Linear variable", + "Cyclic", "Cyclic, SIMPLE-TLV", + }; + printf("%-15s%s\n", "EF structure:", structs[file.ef_structure]); + } + printf("\n"); + if (not_current) { + r = sc_select_file(card, ¤t_path, NULL); + if (r) { + printf("unable to select parent file: %s\n", sc_strerror(r)); + die(1); + } + } + return 0; +} + +int handle_cmd(int cmd, const char *arg) +{ + int i; + + switch (cmd) { + case 0: + return do_ls(); + case 1: + return do_cd(arg); + case 2: + if (sscanf(arg, "%d", &i) != 1) + return -1; + printf("Debug level set to %d\n", i); + ctx->debug = i; + if (i) { + ctx->use_std_output = 1; + } else + ctx->use_std_output = 0; + return 0; + case 3: + return do_cat(arg); + case 4: + return do_info(arg); + } + return -1; +} + +void usage() +{ + int i; + + printf("Supported commands:\n"); + for (i = 0; i < nr_cmds; i++) + printf(" %s\n", cmds[i]); +} + +int main(int argc, const char *argv[]) +{ + int r; + char line[80], cmd[80], arg[80]; + + printf("OpenSC Explorer version %s\n", sc_version); + + r = sc_establish_context(&ctx); + if (r) { + printf("est ctx failed: %s\n", sc_strerror(r)); + return 1; + } + r = sc_connect_card(ctx, 0, &card); + if (r) { + printf("connect card failed: %s\n", sc_strerror(r)); + return 1; + } + sc_lock(card); + + sc_format_path("3F00", ¤t_path); + r = sc_select_file(card, ¤t_path, ¤t_file); + if (r) { + printf("unable to select MF: %s\n", sc_strerror(r)); + return 1; + } + while (1) { + int i; + + printf("OpenSC ["); + for (i = 0; i < current_path.len; i++) { + if ((i & 1) == 0 && i) + printf("/"); + printf("%02X", current_path.value[i]); + } + printf("]> "); + fflush(stdout); + fflush(stdin); + if (fgets(line, sizeof(line), stdin) == NULL) + break; + if (strlen(line) == 0) + break; + r = sscanf(line, "%s %s", cmd, arg); + if (r < 1) + continue; + if (r == 1) + arg[0] = 0; + r = ambiguous_match(cmds, nr_cmds, cmd); + if (r < 0) { + usage(); + continue; + } + handle_cmd(r, arg); + } + die(0); + + return 0; /* not reached */ +} diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index b878b38c..d6df18ea 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -97,32 +97,6 @@ int list_drivers(void) return 0; } -const char * print_acl(unsigned int acl) -{ - static char line[80]; - - if (acl == SC_AC_UNKNOWN) - return "UNKN"; - if (acl == SC_AC_NEVER) - return "NEVR"; - if (acl == SC_AC_NONE) - return "NONE"; - line[0] = 0; - if (acl & SC_AC_CHV1) - strcat(line, "CHV1 "); - if (acl & SC_AC_CHV2) - strcat(line, "CHV2 "); - if (acl & SC_AC_TERM) - strcat(line, "TERM "); - if (acl & SC_AC_PRO) - strcat(line, "PROT "); - if (acl & SC_AC_AUT) - strcat(line, "AUTH "); - - line[strlen(line)-1] = 0; /* get rid of trailing space */ - return line; -} - int print_file(struct sc_card *card, const struct sc_file *file, const struct sc_path *path, int depth) { int r; @@ -174,10 +148,10 @@ int print_file(struct sc_card *card, const struct sc_file *file, const struct sc printf(" "); if (file->type == SC_FILE_TYPE_DF) for (r = 0; r < sizeof(ac_ops_df)/sizeof(ac_ops_df[0]); r++) - printf("%s[%s] ", ac_ops_df[r], print_acl(file->acl[r])); + printf("%s[%s] ", ac_ops_df[r], acl_to_str(file->acl[r])); else for (r = 0; r < sizeof(ac_ops_ef)/sizeof(ac_ops_ef[0]); r++) - printf("%s[%s] ", ac_ops_ef[r], print_acl(file->acl[r])); + printf("%s[%s] ", ac_ops_ef[r], acl_to_str(file->acl[r])); if (file->sec_attr_len) { printf("sec: "); @@ -197,17 +171,17 @@ int print_file(struct sc_card *card, const struct sc_file *file, const struct sc hex_dump(stdout, file->prop_attr, file->prop_attr_len); } printf("\n\n"); -#if 0 +#if 1 if (file->type != SC_FILE_TYPE_DF) { u8 buf[2048]; if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { r = sc_read_binary(card, 0, buf, file->size, 0); if (r > 0) - hex_dump_asc(stdout, buf, r); + hex_dump_asc(stdout, buf, r, 0); } else { r = sc_read_record(card, 0, buf, file->size, 0); if (r > 0) - hex_dump_asc(stdout, buf, r); + hex_dump_asc(stdout, buf, r, 0); } } #endif @@ -220,6 +194,7 @@ int enum_dir(struct sc_path path, int depth) int r; u8 files[MAX_BUFFER_SIZE]; + file.magic = 0; /* make sure the file is invalid */ r = sc_select_file(card, &path, &file); if (r) { fprintf(stderr, "SELECT FILE failed: %s\n", sc_strerror(r)); @@ -329,7 +304,7 @@ int send_apdu(void) printf("Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) - hex_dump_asc(stdout, apdu.resp, apdu.resplen); + hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); } return 0; } diff --git a/src/tools/util.c b/src/tools/util.c index cca512d9..87815642 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -31,14 +31,18 @@ void hex_dump(FILE *f, const u8 *in, int len) fprintf(f, "%02X ", in[i]); } -void hex_dump_asc(FILE *f, const u8 *in, size_t count) +void hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr) { int lines = 0; while (count) { char ascbuf[17]; int i; - + + if (addr >= 0) { + fprintf(f, "%08X: ", addr); + addr += 16; + } for (i = 0; i < count && i < 16; i++) { fprintf(f, "%02X ", *in); if (isprint(*in)) @@ -87,3 +91,28 @@ void print_usage_and_die(const char *pgmname) exit(2); } +const char * acl_to_str(unsigned int acl) +{ + static char line[80]; + + if (acl == SC_AC_UNKNOWN) + return "UNKN"; + if (acl == SC_AC_NEVER) + return "NEVR"; + if (acl == SC_AC_NONE) + return "NONE"; + line[0] = 0; + if (acl & SC_AC_CHV1) + strcat(line, "CHV1 "); + if (acl & SC_AC_CHV2) + strcat(line, "CHV2 "); + if (acl & SC_AC_TERM) + strcat(line, "TERM "); + if (acl & SC_AC_PRO) + strcat(line, "PROT "); + if (acl & SC_AC_AUT) + strcat(line, "AUTH "); + + line[strlen(line)-1] = 0; /* get rid of trailing space */ + return line; +} diff --git a/src/tools/util.h b/src/tools/util.h index e91c1620..35620f9f 100644 --- a/src/tools/util.h +++ b/src/tools/util.h @@ -23,7 +23,8 @@ extern const char *option_help[]; void print_binary(FILE *f, const u8 *buf, int count); void hex_dump(FILE *f, const u8 *in, int len); -void hex_dump_asc(FILE *f, const u8 *in, size_t count); +void hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr); void print_usage_and_die(const char *pgmname); +const char * acl_to_str(unsigned int acl); #endif