diff --git a/ccid/Makefile b/ccid/Makefile
index 09a0461..50ef05f 100644
--- a/ccid/Makefile
+++ b/ccid/Makefile
@@ -13,17 +13,20 @@ CFLAGS = -Wall -g
OPENSSL_CFLAGS = `pkg-config --cflags --libs libssl`
OPENSC_CFLAGS = `pkg-config --cflags --libs libopensc`
PTHREAD_CFLAGS = -pthread
-a_flags = $(CFLAGS) $(OPENSC_CFLAGS) $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS)
+a_flags = $(CFLAGS) $(OPENSC_CFLAGS) $(PTHREAD_CFLAGS)
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
TARGETS = ccid
-CCID_OBJ = ccid.o sm.o usbstring.o usb.o
+CCID_OBJ = ccid.o sm.o usbstring.o usb.o util.o
+PTOOL_OBJ = ccid.o sm.o pace-tool.o util.o pace.o pace_lib.o
ifdef PACE
CCID_OBJ += pace.o pace_lib.o
+ TARGETS += pace-tool
+ a_flags += $(OPENSSL_CFLAGS)
else
a_flags += -DNO_PACE
endif
@@ -34,6 +37,8 @@ all: $(TARGETS)
ccid: $(CCID_OBJ)
$(CC) $^ -o $@ $(a_flags)
+pace-tool: $(PTOOL_OBJ)
+ $(CC) $^ -o $@ $(a_flags)
%.o: %.c %.h
$(CC) $< -o $@ -c $(a_flags)
%.o: %.c
@@ -42,6 +47,7 @@ ccid: $(CCID_OBJ)
install: $(TARGETS) installdirs
$(INSTALL_PROGRAM) ccid $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) pace-tool $(DESTDIR)$(bindir)
.PHONY: installdirs
installdirs:
@@ -54,7 +60,8 @@ install-strip:
.PHONY: uninstall
uninstall:
rm -f $(DESTDIR)$(bindir)/ccid
+ rm -f $(DESTDIR)$(bindir)/pace-tool
.PHONY: clean
clean:
- rm -f $(TARGETS) $(CCID_OBJ)
+ rm -f $(TARGETS) $(CCID_OBJ) $(PTOOL_OBJ)
diff --git a/ccid/pace-tool.c b/ccid/pace-tool.c
new file mode 100644
index 0000000..70ecb81
--- /dev/null
+++ b/ccid/pace-tool.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2009 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+#include "ccid.h"
+#include "util.h"
+#include
+#include
+
+static int verbose = 0;
+static int doinfo = 0;
+static u8 dopacetest = 0;
+static u8 dochangepin = 0;
+static const char *newpin = NULL;
+static int usb_reader_num = -1;
+static const char *pin = NULL;
+static const char *cdriver = NULL;
+
+#define OPT_HELP 'h'
+#define OPT_READER 'r'
+#define OPT_PIN 'i'
+#define OPT_PUK 'u'
+#define OPT_CAN 'a'
+#define OPT_MRZ 'z'
+#define OPT_CHANGE_PIN 'I'
+#define OPT_CHANGE_CAN 'A'
+#define OPT_VERBOSE 'v'
+#define OPT_INFO 'o'
+#define OPT_CARD 'c'
+
+static const struct option options[] = {
+ { "help", no_argument, NULL, OPT_HELP },
+ { "reader", required_argument, NULL, OPT_READER },
+ { "card-driver", required_argument, NULL, OPT_CARD },
+ { "test-pin", optional_argument, NULL, OPT_PIN },
+ { "test-puk", optional_argument, NULL, OPT_PUK },
+ { "test-can", optional_argument, NULL, OPT_CAN },
+ { "test-mrz", optional_argument, NULL, OPT_MRZ },
+ { "new-pin", optional_argument, NULL, OPT_CHANGE_PIN },
+ { "new-can", optional_argument, NULL, OPT_CHANGE_CAN },
+ { "verbose", no_argument, NULL, OPT_VERBOSE },
+ { "info", no_argument, NULL, OPT_INFO },
+ { NULL, 0, NULL, 0 }
+};
+static const char *option_help[] = {
+ "Print help and exit",
+ "Number of reader to use (default: auto-detect)",
+ "Which card driver to use (default: auto-detect)",
+ "Run PACE with PIN",
+ "Run PACE with PUK",
+ "Run PACE with CAN",
+ "Run PACE with MRZ",
+ "Change PIN when PACE is finished",
+ "Change CAN when PACE is finished",
+ "Use (several times) to be more verbose",
+ "Print version, available readers and drivers.",
+};
+
+int
+main (int argc, char **argv)
+{
+ int i, oindex = 0;
+
+ while (1) {
+ i = getopt_long(argc, argv, "hr:i::u::a::z::I::A::voc:", options, &oindex);
+ if (i == -1)
+ break;
+ switch (i) {
+ case OPT_HELP:
+ print_usage(argv[0] , options, option_help);
+ exit(0);
+ break;
+ case OPT_READER:
+ if (sscanf(optarg, "%d", &usb_reader_num) != 1) {
+ parse_error(argv[0], options, option_help, optarg, oindex);
+ exit(2);
+ }
+ break;
+ case OPT_CARD:
+ cdriver = optarg;
+ break;
+ case OPT_VERBOSE:
+ verbose++;
+ break;
+ case OPT_INFO:
+ doinfo++;
+ break;
+ case OPT_PUK:
+ /* PACE_PIN from openssl/pace.h */
+ dopacetest = 4;
+ pin = optarg;
+ break;
+ case OPT_PIN:
+ /* PACE_PIN from openssl/pace.h */
+ dopacetest = 3;
+ pin = optarg;
+ break;
+ case OPT_CAN:
+ /* PACE_PIN from openssl/pace.h */
+ dopacetest = 2;
+ pin = optarg;
+ break;
+ case OPT_MRZ:
+ /* PACE_MRZ from openssl/pace.h */
+ dopacetest = 1;
+ pin = optarg;
+ break;
+ case OPT_CHANGE_CAN:
+ dochangepin = 2;
+ newpin = optarg;
+ break;
+ case OPT_CHANGE_PIN:
+ dochangepin = 3;
+ newpin = optarg;
+ break;
+ case '?':
+ /* fall through */
+ default:
+ exit(1);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf (stderr, "Unknown argument%s:", optind+1 == argc ? "" : "s");
+ while (optind < argc) {
+ fprintf(stderr, " \"%s\"", argv[optind++]);
+ fprintf(stderr, "%c", optind == argc ? '\n' : ',');
+ }
+ exit(1);
+ }
+
+
+ if (doinfo) {
+ fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" ,
+ argv[0]);
+ return ccid_print_avail(verbose);
+ }
+
+ if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) {
+ perror("Can't initialize ccid");
+ return 1;
+ }
+
+ i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin),
+ dochangepin, newpin, !newpin ? 0 : strlen(newpin));
+ ccid_shutdown();
+ return i;
+}
diff --git a/ccid/usb.c b/ccid/usb.c
index d2291c7..9db95f2 100644
--- a/ccid/usb.c
+++ b/ccid/usb.c
@@ -35,7 +35,6 @@
#include
#include
#include
-#include
//#include
//
#include
@@ -47,6 +46,7 @@
#include "usbstring.h"
#include "ccid.h"
+#include "util.h"
#define DRIVER_VENDOR_NUM 0x0D46 /* KOBIL Systems */
#define DRIVER_PRODUCT_NUM 0x3010 /* KOBIL Class 3 Reader */
@@ -57,23 +57,13 @@ static int debug = 0;
static int dohid = 0;
static int doint = 0;
static int doinfo = 0;
-static u8 dopacetest = 0;
-static u8 dochangepin = 0;
-static const char *newpin = NULL;
static int usb_reader_num = -1;
-static const char *pin = NULL;
static const char *cdriver = NULL;
#define OPT_HELP 'h'
#define OPT_INTERRUPT 'n'
#define OPT_READER 'r'
#define OPT_SERIAL 's'
-#define OPT_PIN 'i'
-#define OPT_PUK 'u'
-#define OPT_CAN 'a'
-#define OPT_MRZ 'z'
-#define OPT_CHANGE_PIN 'I'
-#define OPT_CHANGE_CAN 'A'
#define OPT_PRODUCT 'p'
#define OPT_VENDOR 'e'
#define OPT_VERBOSE 'v'
@@ -85,12 +75,6 @@ static const struct option options[] = {
{ "help", no_argument, NULL, OPT_HELP },
{ "reader", required_argument, NULL, OPT_READER },
{ "card-driver", required_argument, NULL, OPT_CARD },
- { "test-pin", optional_argument, NULL, OPT_PIN },
- { "test-puk", optional_argument, NULL, OPT_PUK },
- { "test-can", optional_argument, NULL, OPT_CAN },
- { "test-mrz", optional_argument, NULL, OPT_MRZ },
- { "new-pin", optional_argument, NULL, OPT_CHANGE_PIN },
- { "new-can", optional_argument, NULL, OPT_CHANGE_CAN },
{ "serial", required_argument, NULL, OPT_SERIAL },
{ "product", required_argument, NULL, OPT_PRODUCT },
{ "vendor", required_argument, NULL, OPT_VENDOR },
@@ -104,12 +88,6 @@ static const char *option_help[] = {
"Print help and exit",
"Number of reader to use (default: auto-detect)",
"Which card driver to use (default: auto-detect)",
- "Run PACE with PIN",
- "Run PACE with PUK",
- "Run PACE with CAN",
- "Run PACE with MRZ",
- "Change PIN when PACE is finished",
- "Change CAN when PACE is finished",
"USB serial number (default: random)",
"USB product ID (default: 0x3010)",
"USB vendor ID (default: 0x0D46)",
@@ -1716,55 +1694,6 @@ done:
return 0;
}
-/*-------------------------------------------------------------------------*/
-void print_usage(const char *app_name, const struct option options[],
- const char *option_help[])
-{
- int i = 0;
- printf("Usage: %s [OPTIONS]\nOptions:\n", app_name);
-
- while (options[i].name) {
- char buf[40], tmp[5];
- const char *arg_str;
-
- /* Skip "hidden" options */
- if (option_help[i] == NULL) {
- i++;
- continue;
- }
-
- if (options[i].val > 0 && options[i].val < 128)
- sprintf(tmp, "-%c", options[i].val);
- else
- tmp[0] = 0;
- switch (options[i].has_arg) {
- case 1:
- arg_str = " ";
- break;
- case 2:
- arg_str = " [arg]";
- break;
- default:
- arg_str = "";
- break;
- }
- sprintf(buf, "--%-13s%s%s", options[i].name, tmp, arg_str);
- if (strlen(buf) > 24) {
- printf(" %s\n", buf);
- buf[0] = '\0';
- }
- printf(" %-24s %s\n", buf, option_help[i]);
- i++;
- }
-}
-
-void parse_error(const char *app_name, const char *optarg, int opt_ind)
-{
- printf("Could not parse %s ('%s').\n", options[opt_ind].name, optarg);
- print_usage(app_name , options, option_help);
- exit(2);
-}
-
int
main (int argc, char **argv)
{
@@ -1789,20 +1718,28 @@ main (int argc, char **argv)
exit(0);
break;
case OPT_READER:
- if (sscanf(optarg, "%d", &usb_reader_num) != 1)
- parse_error(argv[0], optarg, oindex);
+ if (sscanf(optarg, "%d", &usb_reader_num) != 1) {
+ parse_error(argv[0], options, option_help, optarg, oindex);
+ exit(2);
+ }
break;
case OPT_SERIAL:
- if (sscanf(optarg, "%56s", serial) != 1)
- parse_error(argv[0], optarg, oindex);
+ if (sscanf(optarg, "%56s", serial) != 1) {
+ parse_error(argv[0], options, option_help, optarg, oindex);
+ exit(2);
+ }
break;
case OPT_PRODUCT:
- if (sscanf(optarg, "%x", &productid) != 1)
- parse_error(argv[0], optarg, oindex);
+ if (sscanf(optarg, "%x", &productid) != 1) {
+ parse_error(argv[0], options, option_help, optarg, oindex);
+ exit(2);
+ }
break;
case OPT_VENDOR:
- if (sscanf(optarg, "%x", &vendorid) != 1)
- parse_error(argv[0], optarg, oindex);
+ if (sscanf(optarg, "%x", &vendorid) != 1) {
+ parse_error(argv[0], options, option_help, optarg, oindex);
+ exit(2);
+ }
break;
case OPT_CARD:
cdriver = optarg;
@@ -1813,34 +1750,6 @@ main (int argc, char **argv)
case OPT_INFO:
doinfo++;
break;
- case OPT_PUK:
- /* PACE_PIN from openssl/pace.h */
- dopacetest = 4;
- pin = optarg;
- break;
- case OPT_PIN:
- /* PACE_PIN from openssl/pace.h */
- dopacetest = 3;
- pin = optarg;
- break;
- case OPT_CAN:
- /* PACE_PIN from openssl/pace.h */
- dopacetest = 2;
- pin = optarg;
- break;
- case OPT_MRZ:
- /* PACE_MRZ from openssl/pace.h */
- dopacetest = 1;
- pin = optarg;
- break;
- case OPT_CHANGE_CAN:
- dochangepin = 2;
- newpin = optarg;
- break;
- case OPT_CHANGE_PIN:
- dochangepin = 3;
- newpin = optarg;
- break;
case '?':
/* fall through */
default:
@@ -1870,13 +1779,6 @@ main (int argc, char **argv)
return 1;
}
- if (dopacetest) {
- i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin),
- dochangepin, newpin, !newpin ? 0 : strlen(newpin));
- ccid_shutdown();
- return i;
- }
-
if (verbose)
fprintf (stderr, "serial=\"%s\"\n", serial);
diff --git a/ccid/util.c b/ccid/util.c
new file mode 100644
index 0000000..e7f704f
--- /dev/null
+++ b/ccid/util.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+#include "util.h"
+#include
+#include
+
+void print_usage(const char *app_name, const struct option options[],
+ const char *option_help[])
+{
+ int i = 0;
+ printf("Usage: %s [OPTIONS]\nOptions:\n", app_name);
+
+ while (options[i].name) {
+ char buf[40], tmp[5];
+ const char *arg_str;
+
+ /* Skip "hidden" options */
+ if (option_help[i] == NULL) {
+ i++;
+ continue;
+ }
+
+ if (options[i].val > 0 && options[i].val < 128)
+ sprintf(tmp, "-%c", options[i].val);
+ else
+ tmp[0] = 0;
+ switch (options[i].has_arg) {
+ case 1:
+ arg_str = " ";
+ break;
+ case 2:
+ arg_str = " [arg]";
+ break;
+ default:
+ arg_str = "";
+ break;
+ }
+ sprintf(buf, "--%-13s%s%s", options[i].name, tmp, arg_str);
+ if (strlen(buf) > 24) {
+ printf(" %s\n", buf);
+ buf[0] = '\0';
+ }
+ printf(" %-24s %s\n", buf, option_help[i]);
+ i++;
+ }
+}
+
+void parse_error(const char *app_name, const struct option options[],
+ const char *option_help[], const char *optarg, int opt_ind)
+{
+ printf("Could not parse %s ('%s').\n", options[opt_ind].name, optarg);
+ print_usage(app_name , options, option_help);
+}
diff --git a/ccid/util.h b/ccid/util.h
new file mode 100644
index 0000000..bf5665d
--- /dev/null
+++ b/ccid/util.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 Frank Morgner
+ *
+ * This file is part of ccid.
+ *
+ * ccid is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * ccid 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 General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ccid. If not, see .
+ */
+#ifndef _CCID_UTIL_H
+#define _CCID_UTIL_H
+
+#include
+
+void print_usage(const char *app_name, const struct option options[],
+ const char *option_help[]);
+void parse_error(const char *app_name, const struct option options[],
+ const char *option_help[], const char *optarg, int opt_ind);
+
+#endif