- 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
This commit is contained in:
jey 2002-01-09 01:03:10 +00:00
parent 6778d0b929
commit 269df3a6da
10 changed files with 605 additions and 72 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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:

View File

@ -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 <buf>. 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);

View File

@ -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

445
src/tools/opensc-explorer.c Normal file
View File

@ -0,0 +1,445 @@
/*
* opensc-explorer.c: A shell for accessing SmartCards with libopensc
*
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
*
* 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 <opensc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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", &current_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", &current_file);
return -1;
}
cur += 2;
count -= 2;
print_file(&file);
r = sc_select_file(card, &current_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, &current_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 <file_id>\n");
return -1;
}
strcpy(buf, "I");
strcat(buf, arg);
sc_format_path(buf, &path);
if (path.len != 2) {
printf("Usage: cd <file_id>\n");
return -1;
}
r = sc_select_file(card, &path, &file);
if (r) {
check_ret(r, SC_AC_OP_SELECT, "unable to select DF", &current_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", &current_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, &current_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, &current_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", &current_path);
r = sc_select_file(card, &current_path, &current_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 */
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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