From 170ec3c703803d23e609632c315756891c9d4250 Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Tue, 4 May 2010 20:03:54 +0000 Subject: [PATCH] cleaned up command line options of pace-tool and made it independant from ccid git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@89 96b47cad-a561-4643-ad3b-153ac7d7599c --- ccid/Makefile | 4 +- ccid/ccid.c | 205 ++--------------------------------------------- ccid/ccid.h | 5 -- ccid/pace-tool.c | 69 ++++++++++------ ccid/pace.c | 4 +- ccid/usb.c | 2 +- ccid/util.c | 175 ++++++++++++++++++++++++++++++++++++++++ ccid/util.h | 7 ++ 8 files changed, 240 insertions(+), 231 deletions(-) diff --git a/ccid/Makefile b/ccid/Makefile index 50ef05f..4989cc2 100644 --- a/ccid/Makefile +++ b/ccid/Makefile @@ -21,7 +21,7 @@ INSTALL_PROGRAM = $(INSTALL) TARGETS = ccid 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 +PTOOL_OBJ = sm.o pace-tool.o util.o pace.o pace_lib.o ifdef PACE CCID_OBJ += pace.o pace_lib.o @@ -64,4 +64,4 @@ uninstall: .PHONY: clean clean: - rm -f $(TARGETS) $(CCID_OBJ) $(PTOOL_OBJ) + rm -f $(TARGETS) $(CCID_OBJ) pace-tool $(PTOOL_OBJ) diff --git a/ccid/ccid.c b/ccid/ccid.c index f38729f..465b06c 100644 --- a/ccid/ccid.c +++ b/ccid/ccid.c @@ -27,9 +27,7 @@ #include #include "ccid.h" -#ifndef NO_PACE -#include "pace.h" -#endif +#include "util.h" static sc_context_t *ctx = NULL; static sc_card_t *card_in_slot[SC_MAX_SLOTS]; @@ -117,56 +115,19 @@ detect_card_presence(int slot) int ccid_initialize(int reader_id, const char *cdriver, int verbose) { - unsigned int i, reader_count; - - int r = sc_context_create(&ctx, NULL); - if (r < 0) { - printf("Failed to create initial context: %s", sc_strerror(r)); - return r; - } - - if (cdriver != NULL) { - r = sc_set_card_driver(ctx, cdriver); - if (r < 0) { - sc_error(ctx, "Card driver '%s' not found!\n", cdriver); - return r; - } - } - - ctx->debug = verbose; + int i; for (i = 0; i < sizeof *card_in_slot; i++) { card_in_slot[i] = NULL; } - reader_count = sc_ctx_get_reader_count(ctx); + i = initialize(reader_id, cdriver, verbose, &ctx, &reader); + if (i < 0) + return i; - if (reader_count == 0) - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND); - - if (reader_id < 0) { - /* Automatically try to skip to a reader with a card if reader not specified */ - for (i = 0; i < reader_count; i++) { - reader = sc_ctx_get_reader(ctx, i); - if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) { - reader_id = i; - sc_debug(ctx, "Using reader with a card: %s", reader->name); - break; - } - } - if (reader_id >= reader_count) { - /* no reader found, use the first */ - reader_id = 0; - } - } - - if (reader_id >= reader_count) - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND); - - reader = sc_ctx_get_reader(ctx, reader_id); ccid_desc.bMaxSlotIndex = reader->slot_count - 1; - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS); + return SC_SUCCESS; } void ccid_shutdown() @@ -181,71 +142,6 @@ void ccid_shutdown() sc_release_context(ctx); } -int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu) -{ - const __u8 *p; - size_t len0; - - if (!buf || !apdu) - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); - - len0 = len; - if (len < 4) { - sc_error(ctx, "APDU too short (must be at least 4 bytes)"); - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); - } - - memset(apdu, 0, sizeof(*apdu)); - p = buf; - apdu->cla = *p++; - apdu->ins = *p++; - apdu->p1 = *p++; - apdu->p2 = *p++; - len -= 4; - if (len > 1) { - apdu->lc = *p++; - len--; - apdu->data = p; - apdu->datalen = apdu->lc; - if (len < apdu->lc) { - sc_error(ctx, "APDU too short (need %lu bytes)\n", - (unsigned long) apdu->lc - len); - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); - } - len -= apdu->lc; - p += apdu->lc; - if (len) { - apdu->le = *p++; - if (apdu->le == 0) - apdu->le = 256; - len--; - apdu->cse = SC_APDU_CASE_4_SHORT; - } else { - apdu->cse = SC_APDU_CASE_3_SHORT; - } - if (len) { - sc_error(ctx, "APDU too long (%lu bytes extra)\n", - (unsigned long) len); - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); - } - } else if (len == 1) { - apdu->le = *p++; - if (apdu->le == 0) - apdu->le = 256; - len--; - apdu->cse = SC_APDU_CASE_2_SHORT; - } else { - apdu->cse = SC_APDU_CASE_1; - } - - apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; - - sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x", - (unsigned int) len0, apdu->ins, apdu->p1, apdu->p2); - - SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS); -} - static int get_rapdu(sc_apdu_t *apdu, size_t slot, __u8 **buf, size_t *resplen) { int sc_result; @@ -542,7 +438,7 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, __u8** out, size_t *outlen) if (request->bSlot > sizeof *card_in_slot) sc_result = SC_ERROR_INVALID_DATA; else { - sc_result = build_apdu(abDataIn, request->dwLength, &apdu); + sc_result = build_apdu(ctx, abDataIn, request->dwLength, &apdu); if (sc_result >= 0) sc_result = get_rapdu(&apdu, request->bSlot, &abDataOut, &resplen); } @@ -903,7 +799,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, __u8** out, size_t *outlen) goto err; } - sc_result = build_apdu(abPINApdu, apdulen, &apdu); + sc_result = build_apdu(ctx, abPINApdu, apdulen, &apdu); if (sc_result < 0) goto err; apdu.sensitive = 1; @@ -1306,88 +1202,3 @@ int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout) return 0; } - -#ifdef NO_PACE -int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen, - u8 new_pin_id, const char *new_pin, size_t new_pinlen) -{ - sc_error(ctx, "ccid not compiled with support for PACE."); - - return SC_ERROR_NOT_SUPPORTED; -} -#else -int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen, - u8 new_pin_id, const char *new_pin, size_t new_pinlen) -{ - int i; - for (i = 0; i < sizeof *card_in_slot; i++) { - if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) { - if (!card_in_slot[i] || !sc_card_valid(card_in_slot[i])) { - sc_connect_card(reader, i, &card_in_slot[i]); - } - return pace_test(card_in_slot[i], pin_id, pin, pinlen, - new_pin_id, new_pin, new_pinlen); - } - } - - sc_error(ctx, "No card found."); - - return SC_ERROR_SLOT_NOT_FOUND; -} -#endif - -static int ccid_list_readers(sc_context_t *ctx) -{ - unsigned int i, rcount = sc_ctx_get_reader_count(ctx); - - if (rcount == 0) { - printf("No smart card readers found.\n"); - return 0; - } - printf("Readers known about:\n"); - printf("Nr. Driver Name\n"); - for (i = 0; i < rcount; i++) { - sc_reader_t *screader = sc_ctx_get_reader(ctx, i); - printf("%-7d%-11s%s\n", i, screader->driver->short_name, - screader->name); - } - - return 0; -} - -static int ccid_list_drivers(sc_context_t *ctx) -{ - int i; - - if (ctx->card_drivers[0] == NULL) { - printf("No card drivers installed!\n"); - return 0; - } - printf("Configured card drivers:\n"); - for (i = 0; ctx->card_drivers[i] != NULL; i++) { - printf(" %-16s %s\n", ctx->card_drivers[i]->short_name, - ctx->card_drivers[i]->name); - } - - return 0; -} - -int ccid_print_avail(int verbose) -{ - sc_context_t *ctx = NULL; - - int r; - r = sc_context_create(&ctx, NULL); - if (r) { - fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); - return 1; - } - ctx->debug = verbose; - - r = ccid_list_readers(ctx)|ccid_list_drivers(ctx); - - if (ctx) - sc_release_context(ctx); - - return r; -} diff --git a/ccid/ccid.h b/ccid/ccid.h index 5a510ad..1a91d3f 100644 --- a/ccid/ccid.h +++ b/ccid/ccid.h @@ -265,17 +265,12 @@ struct hid_class_descriptor { __u8 bNumDescriptors; } __attribute__ ((packed)); -int ccid_print_avail(int verbose); int ccid_initialize(int reader_id, const char *cdriver, int verbose); void ccid_shutdown(); int ccid_parse_bulkin(const __u8* inbuf, __u8** outbuf); int ccid_parse_control(struct usb_ctrlrequest *setup, __u8 **outbuf); int ccid_state_changed(RDR_to_PC_NotifySlotChange_t **slotchange, int timeout); -int ccid_testpace(u8 pin_id, const char *pin, size_t pinlen, - u8 new_pin_id, const char *new_pin, size_t new_pinlen); - -int build_apdu(const __u8 *buf, size_t len, sc_apdu_t *apdu); #ifdef __cplusplus } diff --git a/ccid/pace-tool.c b/ccid/pace-tool.c index 70ecb81..9be165d 100644 --- a/ccid/pace-tool.c +++ b/ccid/pace-tool.c @@ -16,20 +16,23 @@ * 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 "pace.h" #include #include static int verbose = 0; static int doinfo = 0; -static u8 dopacetest = 0; +static u8 pin_id = 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; +static sc_context_t *ctx = NULL; +static sc_reader_t *reader; + #define OPT_HELP 'h' #define OPT_READER 'r' #define OPT_PIN 'i' @@ -37,7 +40,6 @@ static const char *cdriver = NULL; #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' @@ -46,12 +48,11 @@ 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 }, + { "pin", optional_argument, NULL, OPT_PIN }, + { "puk", optional_argument, NULL, OPT_PUK }, + { "can", optional_argument, NULL, OPT_CAN }, + { "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 } @@ -64,19 +65,39 @@ static const char *option_help[] = { "Run PACE with PUK", "Run PACE with CAN", "Run PACE with MRZ", - "Change PIN when PACE is finished", - "Change CAN when PACE is finished", + "Install a new PIN", "Use (several times) to be more verbose", "Print version, available readers and drivers.", }; +int testpace(u8 pin_id, const char *pin, size_t pinlen, + u8 new_pin_id, const char *new_pin, size_t new_pinlen) +{ + int i; + sc_card_t *card; + for (i = 0; i < SC_MAX_SLOTS; i++) { + if (sc_detect_card_presence(reader, 0) & SC_SLOT_CARD_PRESENT) { + sc_connect_card(reader, i, &card); + i = pace_test(card, pin_id, pin, pinlen, + new_pin_id, new_pin, new_pinlen); + if (card && sc_card_valid(card)) + sc_disconnect_card(card, 0); + return i; + } + } + + fprintf (stderr, "No card found."); + + return SC_ERROR_SLOT_NOT_FOUND; +} + 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); + i = getopt_long(argc, argv, "hr:i::u::a::z::I::voc:", options, &oindex); if (i == -1) break; switch (i) { @@ -101,28 +122,24 @@ main (int argc, char **argv) break; case OPT_PUK: /* PACE_PIN from openssl/pace.h */ - dopacetest = 4; + pin_id = 4; pin = optarg; break; case OPT_PIN: /* PACE_PIN from openssl/pace.h */ - dopacetest = 3; + pin_id = 3; pin = optarg; break; case OPT_CAN: /* PACE_PIN from openssl/pace.h */ - dopacetest = 2; + pin_id = 2; pin = optarg; break; case OPT_MRZ: /* PACE_MRZ from openssl/pace.h */ - dopacetest = 1; + pin_id = 1; pin = optarg; break; - case OPT_CHANGE_CAN: - dochangepin = 2; - newpin = optarg; - break; case OPT_CHANGE_PIN: dochangepin = 3; newpin = optarg; @@ -148,16 +165,20 @@ main (int argc, char **argv) if (doinfo) { fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" , argv[0]); - return ccid_print_avail(verbose); + return print_avail(verbose); } - if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) { - perror("Can't initialize ccid"); + i = initialize(usb_reader_num, cdriver, verbose, &ctx, &reader); + if (i < 0) { + perror("Can't initialize reader"); return 1; } - i = ccid_testpace(dopacetest, pin, !pin ? 0 : strlen(pin), + i = testpace(pin_id, pin, !pin ? 0 : strlen(pin), dochangepin, newpin, !newpin ? 0 : strlen(newpin)); - ccid_shutdown(); + + if (ctx) + sc_release_context(ctx); + return i; } diff --git a/ccid/pace.c b/ccid/pace.c index 8c6cd42..56c735f 100644 --- a/ccid/pace.c +++ b/ccid/pace.c @@ -18,7 +18,7 @@ */ #include "pace.h" #include "sm.h" -#include "ccid.h" +#include "util.h" #include #include #include @@ -953,7 +953,7 @@ int pace_test(sc_card_t *card, sc_error(card->ctx, "Could not format binary string"); } - r = build_apdu(buf, apdulen, &apdu); + r = build_apdu(card->ctx, buf, apdulen, &apdu); if (r < 0) { sc_error(card->ctx, "Could not format APDU"); continue; diff --git a/ccid/usb.c b/ccid/usb.c index 9db95f2..14691cc 100644 --- a/ccid/usb.c +++ b/ccid/usb.c @@ -1771,7 +1771,7 @@ main (int argc, char **argv) if (doinfo) { fprintf(stderr, "%s 0.9 written by Frank Morgner.\n\n" , argv[0]); - return ccid_print_avail(verbose); + return print_avail(verbose); } if (ccid_initialize(usb_reader_num, cdriver, verbose) < 0) { diff --git a/ccid/util.c b/ccid/util.c index e7f704f..7207a02 100644 --- a/ccid/util.c +++ b/ccid/util.c @@ -19,6 +19,7 @@ #include "util.h" #include #include +#include void print_usage(const char *app_name, const struct option options[], const char *option_help[]) @@ -67,3 +68,177 @@ void parse_error(const char *app_name, const struct option options[], printf("Could not parse %s ('%s').\n", options[opt_ind].name, optarg); print_usage(app_name , options, option_help); } + +int initialize(int reader_id, const char *cdriver, int verbose, + sc_context_t **ctx, sc_reader_t **reader) +{ + unsigned int i, reader_count; + + if (!ctx || !reader) + return SC_ERROR_INVALID_ARGUMENTS; + + int r = sc_context_create(ctx, NULL); + if (r < 0) { + printf("Failed to create initial context: %s", sc_strerror(r)); + return r; + } + + if (cdriver != NULL) { + r = sc_set_card_driver(*ctx, cdriver); + if (r < 0) { + sc_error(*ctx, "Card driver '%s' not found!\n", cdriver); + return r; + } + } + + (*ctx)->debug = verbose; + + reader_count = sc_ctx_get_reader_count(*ctx); + + if (reader_count == 0) + SC_FUNC_RETURN((*ctx), SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND); + + if (reader_id < 0) { + /* Automatically try to skip to a reader with a card if reader not specified */ + for (i = 0; i < reader_count; i++) { + *reader = sc_ctx_get_reader(*ctx, i); + if (sc_detect_card_presence(*reader, 0) & SC_SLOT_CARD_PRESENT) { + reader_id = i; + sc_debug(*ctx, "Using reader with a card: %s", (*reader)->name); + break; + } + } + if (reader_id >= reader_count) { + /* no reader found, use the first */ + reader_id = 0; + } + } + + if (reader_id >= reader_count) + SC_FUNC_RETURN((*ctx), SC_LOG_TYPE_ERROR, SC_ERROR_NO_READERS_FOUND); + + *reader = sc_ctx_get_reader(*ctx, reader_id); + + SC_FUNC_RETURN((*ctx), SC_LOG_TYPE_ERROR, SC_SUCCESS); +} + +static int list_readers(sc_context_t *ctx) +{ + unsigned int i, rcount = sc_ctx_get_reader_count(ctx); + + if (rcount == 0) { + printf("No smart card readers found.\n"); + return 0; + } + printf("Readers known about:\n"); + printf("Nr. Driver Name\n"); + for (i = 0; i < rcount; i++) { + sc_reader_t *screader = sc_ctx_get_reader(ctx, i); + printf("%-7d%-11s%s\n", i, screader->driver->short_name, + screader->name); + } + + return 0; +} + +static int list_drivers(sc_context_t *ctx) +{ + int i; + + if (ctx->card_drivers[0] == NULL) { + printf("No card drivers installed!\n"); + return 0; + } + printf("Configured card drivers:\n"); + for (i = 0; ctx->card_drivers[i] != NULL; i++) { + printf(" %-16s %s\n", ctx->card_drivers[i]->short_name, + ctx->card_drivers[i]->name); + } + + return 0; +} + +int print_avail(int verbose) +{ + sc_context_t *ctx = NULL; + + int r; + r = sc_context_create(&ctx, NULL); + if (r) { + fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); + return 1; + } + ctx->debug = verbose; + + r = list_readers(ctx)|list_drivers(ctx); + + if (ctx) + sc_release_context(ctx); + + return r; +} + +int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu) +{ + const u8 *p; + size_t len0; + + if (!buf || !apdu) + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); + + len0 = len; + if (len < 4) { + sc_error(ctx, "APDU too short (must be at least 4 bytes)"); + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); + } + + memset(apdu, 0, sizeof(*apdu)); + p = buf; + apdu->cla = *p++; + apdu->ins = *p++; + apdu->p1 = *p++; + apdu->p2 = *p++; + len -= 4; + if (len > 1) { + apdu->lc = *p++; + len--; + apdu->data = p; + apdu->datalen = apdu->lc; + if (len < apdu->lc) { + sc_error(ctx, "APDU too short (need %lu bytes)\n", + (unsigned long) apdu->lc - len); + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); + } + len -= apdu->lc; + p += apdu->lc; + if (len) { + apdu->le = *p++; + if (apdu->le == 0) + apdu->le = 256; + len--; + apdu->cse = SC_APDU_CASE_4_SHORT; + } else { + apdu->cse = SC_APDU_CASE_3_SHORT; + } + if (len) { + sc_error(ctx, "APDU too long (%lu bytes extra)\n", + (unsigned long) len); + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_ERROR_INVALID_DATA); + } + } else if (len == 1) { + apdu->le = *p++; + if (apdu->le == 0) + apdu->le = 256; + len--; + apdu->cse = SC_APDU_CASE_2_SHORT; + } else { + apdu->cse = SC_APDU_CASE_1; + } + + apdu->flags = SC_APDU_FLAGS_NO_GET_RESP|SC_APDU_FLAGS_NO_RETRY_WL; + + sc_debug(ctx, "APDU, %d bytes:\tins=%02x p1=%02x p2=%02x", + (unsigned int) len0, apdu->ins, apdu->p1, apdu->p2); + + SC_FUNC_RETURN(ctx, SC_LOG_TYPE_VERBOSE, SC_SUCCESS); +} diff --git a/ccid/util.h b/ccid/util.h index bf5665d..6582b42 100644 --- a/ccid/util.h +++ b/ccid/util.h @@ -20,10 +20,17 @@ #define _CCID_UTIL_H #include +#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); +int print_avail(int verbose); +int initialize(int reader_id, const char *cdriver, int verbose, + sc_context_t **ctx, sc_reader_t **reader); + +int build_apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu); + #endif