From d7022d33000ab0a26a841617041d086b230c7acd Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Fri, 1 Jun 2012 15:35:27 +0200 Subject: [PATCH] ias-ecc: add tool with IAS/ECC specific query operations --- doc/tools/iasecc-tool.1.xml | 81 ++++++++++ doc/tools/tools.xml | 1 + src/tools/Makefile.am | 7 +- src/tools/iasecc-tool.c | 300 ++++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+), 2 deletions(-) create mode 100644 doc/tools/iasecc-tool.1.xml create mode 100644 src/tools/iasecc-tool.c diff --git a/doc/tools/iasecc-tool.1.xml b/doc/tools/iasecc-tool.1.xml new file mode 100644 index 00000000..ba0ac0ab --- /dev/null +++ b/doc/tools/iasecc-tool.1.xml @@ -0,0 +1,81 @@ + + + + iasecc-tool + 1 + OpenSC + OpenSC Tools + opensc + + + + iasecc-tool + displays information about IAS/ECC card + + + + + + iasecc-tool + OPTIONS + + + + + Description + + The iasecc-tool utility is used to display information about IAS/ECC v1.0.1 smart cards. + + + + + Options + + + + + number, + + Specify the reader number number to use. + The default is reader 0. + + + + , + + Get list of the on-card applications. + + + + hex-aid, + + Select hex-aid before processing. + + + + sdo-type, + + List SDOs of the given sdo-type, + present in default or selected application. + + + + , + + + Causes cardos-tool to be more verbose. + Specify this flag several times to enable debug output in the opensc library. + + + + , + + + Causes iasecc-tool to wait for the token + to be inserted into reader. + + + + + + diff --git a/doc/tools/tools.xml b/doc/tools/tools.xml index a109d368..e9fe9179 100644 --- a/doc/tools/tools.xml +++ b/doc/tools/tools.xml @@ -13,6 +13,7 @@ + diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 0a5131ff..783bb2a5 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -5,7 +5,7 @@ EXTRA_DIST = Makefile.mak noinst_HEADERS = util.h bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \ - pkcs11-tool cardos-tool eidenv openpgp-tool + pkcs11-tool cardos-tool eidenv openpgp-tool iasecc-tool if ENABLE_OPENSSL bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool westcos-tool endif @@ -32,7 +32,7 @@ pkcs11_tool_LDADD = \ pkcs15_crypt_SOURCES = pkcs15-crypt.c util.c pkcs15_crypt_LDADD = $(OPTIONAL_OPENSSL_LIBS) cryptoflex_tool_SOURCES = cryptoflex-tool.c util.c -cryptoflex_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) +cryptoflex_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) pkcs15_init_SOURCES = pkcs15-init.c util.c pkcs15_init_LDADD = $(OPTIONAL_OPENSSL_LIBS) cardos_tool_SOURCES = cardos-tool.c util.c @@ -44,6 +44,8 @@ westcos_tool_SOURCES = westcos-tool.c util.c westcos_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) openpgp_tool_SOURCES = openpgp-tool.c util.c openpgp_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) +iasecc_tool_SOURCES = iasecc-tool.c util.c +iasecc_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) if WIN32 opensc_tool_SOURCES += $(top_builddir)/win32/versioninfo.rc @@ -59,4 +61,5 @@ eidenv_SOURCES += $(top_builddir)/win32/versioninfo.rc netkey_tool_SOURCES += $(top_builddir)/win32/versioninfo.rc westcos_tool_SOURCES += $(top_builddir)/win32/versioninfo.rc openpgp_tool_SOURCES += $(top_builddir)/win32/versioninfo.rc +iasecc_tool_SOURCES += $(top_builddir)/win32/versioninfo.rc endif diff --git a/src/tools/iasecc-tool.c b/src/tools/iasecc-tool.c new file mode 100644 index 00000000..1e020e56 --- /dev/null +++ b/src/tools/iasecc-tool.c @@ -0,0 +1,300 @@ +/* + * iasecc-tool.c: Tool for accessing smart cards with libopensc + * + * Copyright (C) 2001 Juha Yrjölä + * Copyright (C) 2011 Viktor TARASOV + * + * 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 "config.h" + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include + +#include "libopensc/opensc.h" +#include "libopensc/cardctl.h" +#include "libopensc/asn1.h" +#include "libopensc/iasecc.h" +#include "util.h" + +static const char *app_name = "iasecc-tool"; + +static char * opt_bind_to_aid = NULL; +static char * opt_reader = NULL; +static char * opt_sdo_tag = 0; +static int opt_wait = 0; +static int verbose = 0; + +enum { + OPT_READER = 0x100, + OPT_BIND_TO_AID, + OPT_LIST_SDOS, + OPT_LIST_APPLICATIONS +}; + +static const struct option options[] = { + { "reader", required_argument, NULL, OPT_READER }, + { "aid", required_argument, NULL, OPT_BIND_TO_AID }, + { "list-applications", no_argument, NULL, OPT_LIST_APPLICATIONS }, + { "list-sdos", required_argument, NULL, OPT_LIST_SDOS }, + { "wait", no_argument, NULL, 'w' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } +}; + +static const char *option_help[] = { + "Uses reader number ", + "Specify AID of the on-card PKCS#15 application to be binded to (in hexadecimal form)", + "List the on-card PKCS#15 applications", + "List the SDOs with the tag in the current ADF", + "Wait for card insertion", + "Verbose operation. Use several times to enable debug output.", + NULL +}; + +static int list_sdos(char *sdo_tag); + +static sc_context_t *ctx = NULL; +static sc_card_t *card = NULL; +static struct sc_pkcs15_card *p15card = NULL; + +static void +_iasecc_print_tlv(char *label, int format_text, struct iasecc_extended_tlv *tlv) +{ + unsigned ii; + + if (!tlv->value) + return; + + printf("%s:\t", label); + for(ii=0; iisize; ii++) { + if (format_text) { + printf("%c", *(tlv->value + ii)); + } + else { + if (ii) printf(":"); + printf("%02X", *(tlv->value + ii)); + } + } + printf("\n"); + +} + +static void +_iasecc_print_docp(struct iasecc_sdo_docp *docp) +{ + _iasecc_print_tlv("\tname:", 1, &docp->name); + _iasecc_print_tlv("\tcontact ACLs", 0, &docp->acls_contact); + _iasecc_print_tlv("\tnon repudiation", 0, &docp->non_repudiation); + _iasecc_print_tlv("\tsize", 0, &docp->size); + _iasecc_print_tlv("\ttries maximum", 0, &docp->tries_maximum); + _iasecc_print_tlv("\ttries remaining", 0, &docp->tries_remaining); + _iasecc_print_tlv("\tusage maximum", 0, &docp->usage_maximum); + _iasecc_print_tlv("\tusage remaining", 0, &docp->usage_remaining); +} + +static void +_iasecc_print_crt(struct sc_crt *crt) +{ + printf("\tCRT #%X:\tusage %02X; algo %02X; ref %02X:%02X:...\n", + crt->tag, crt->usage, crt->algo, crt->refs[0], crt->refs[1]); +} + +static int list_sdos(char *sdo_tag) +{ + struct iasecc_sdo sdo; + struct iasecc_se_info se; + unsigned sdo_class = 0; + int rv, ii, jj; + + if (!sdo_tag) + goto usage; + + if (*sdo_tag == 'x' || *sdo_tag == 'X') + sdo_class = strtol(sdo_tag + 1, NULL, 16); + else if ((strlen(sdo_tag) > 2) && (*(sdo_tag + 1) == 'x' || *(sdo_tag + 1) == 'X')) + sdo_class = strtol(sdo_tag + 2, NULL, 16); + else + sdo_class = strtol(sdo_tag, NULL, 10); + + sdo_class &= 0x7F; + if (sdo_class == IASECC_SDO_CLASS_SE) { + for (ii=1; ii<0x20; ii++) { + memset(&se, 0, sizeof(se)); + se.reference = ii; + + rv = sc_card_ctl(card, SC_CARDCTL_GET_SE_INFO, &se); + if (!rv) { + printf("Found SE #%X\n", se.reference); + _iasecc_print_docp(&se.docp); + for(jj=0; jj"); + return -1; +} + +static int list_apps(FILE *fout) +{ + unsigned j; + int i; + + for (i=0; i < card->app_count; i++) { + struct sc_app_info *info = card->app[i]; + + fprintf(fout, "Application '%s':\n", info->label); + fprintf(fout, "\tAID: "); + for(j=0;jaid.len;j++) + fprintf(fout, "%02X", info->aid.value[j]); + fprintf(fout, "\n"); + + if (info->ddo.value && info->ddo.len) { + fprintf(fout, "\tDDO: "); + for(j=0;jddo.len;j++) + fprintf(fout, "%02X", info->ddo.value[j]); + fprintf(fout, "\n"); + } + + fprintf(fout, "\n"); + } + return 0; +} + +int main(int argc, char * const argv[]) +{ + int err = 0, r, c, long_optind = 0; + int do_list_sdos = 0; + int do_list_apps = 0; + int action_count = 0; + sc_context_param_t ctx_param; + + setbuf(stderr, NULL); + setbuf(stdout, NULL); + + while (1) { + c = getopt_long(argc, argv, "v", options, &long_optind); + if (c == -1) + break; + if (c == '?') + util_print_usage_and_die(app_name, options, option_help, NULL); + switch (c) { + case OPT_LIST_SDOS: + do_list_sdos = 1; + opt_sdo_tag = optarg; + action_count++; + break; + case OPT_LIST_APPLICATIONS: + do_list_apps = 1; + action_count++; + break; + case OPT_BIND_TO_AID: + opt_bind_to_aid = optarg; + break; + case OPT_READER: + opt_reader = optarg; + break; + case 'v': + verbose++; + break; + } + } + if (action_count == 0) + util_print_usage_and_die(app_name, options, option_help, NULL); + + memset(&ctx_param, 0, sizeof(sc_context_param_t)); + ctx_param.app_name = app_name; + + r = sc_context_create(&ctx, &ctx_param); + if (r != SC_SUCCESS) { + fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); + return 1; + } + + /* Only change if not in opensc.conf */ + if (verbose > 1 && ctx->debug == 0) { + ctx->debug = verbose; + sc_ctx_log_to_file(ctx, "stderr"); + } + + if (action_count <= 0) + goto end; + + err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); + if (err) + goto end; + + if (opt_bind_to_aid) { + struct sc_aid aid; + + aid.len = sizeof(aid.value); + if (sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len)) { + fprintf(stderr, "Invalid AID value: '%s'\n", opt_bind_to_aid); + return 1; + } + + r = sc_pkcs15_bind(card, &aid, &p15card); + } + else if (!do_list_sdos) { + r = sc_pkcs15_bind(card, NULL, &p15card); + } + + if (do_list_sdos) { + if ((err = list_sdos(opt_sdo_tag))) + goto end; + action_count--; + } + if (do_list_apps) { + if ((err = list_apps(stdout))) + goto end; + action_count--; + } +end: + if (p15card) + sc_pkcs15_unbind(p15card); + + if (card) { + sc_unlock(card); + sc_disconnect_card(card); + } + if (ctx) + sc_release_context(ctx); + + return err; +}