diff --git a/ccid/pace-tool.c b/ccid/pace-tool.c index e4d696f..86fcc67 100644 --- a/ccid/pace-tool.c +++ b/ccid/pace-tool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Frank Morgner + * Copyright (C) 2010 Frank Morgner * * This file is part of ccid. * @@ -16,11 +16,15 @@ * You should have received a copy of the GNU General Public License along with * ccid. If not, see . */ -#include "util.h" #include "pace.h" +#include "util.h" +#include +#include +#include +#include +#include #include #include -#include static int verbose = 0; static int doinfo = 0; @@ -32,6 +36,7 @@ static const char *pin = NULL; static const char *cdriver = NULL; static sc_context_t *ctx = NULL; +static sc_card_t *card = NULL; static sc_reader_t *reader; #define OPT_HELP 'h' @@ -71,25 +76,134 @@ static const char *option_help[] = { "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 pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id, + const char *newp, size_t newplen) { - 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; + sc_ui_hints_t hints; + char *p = NULL; + int r; + + if (!newplen || !newp) { + memset(&hints, 0, sizeof(hints)); + hints.dialog_name = "ccid.PACE"; + hints.card = card; + hints.prompt = NULL; + hints.obj_label = pace_secret_name(pin_id); + hints.usage = SC_UI_USAGE_NEW_PIN; + r = sc_ui_get_pin(&hints, &p); + if (r < 0) { + sc_error(card->ctx, "Could not read new %s (%s).\n", + hints.obj_label, sc_strerror(r)); + SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); } + newplen = strlen(p); + newp = p; } - fprintf (stderr, "No card found."); + r = pace_reset_retry_counter(ctx, card, pin_id, newp, newplen); - return SC_ERROR_SLOT_NOT_FOUND; + if (p) { + OPENSSL_cleanse(p, newplen); + free(p); + } + + SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); +} + +int pace_test(sc_card_t *card, + enum s_type pin_id, const char *pin, size_t pinlen, + enum s_type new_pin_id, const char *new_pin, size_t new_pinlen) +{ + u8 buf[0xff + 5]; + char *read = NULL; + __u8 *out = NULL; + size_t outlen, readlen = 0, apdulen; + ssize_t linelen; + struct sm_ctx sctx; + sc_apdu_t apdu; + int r; + + memset(&sctx, 0, sizeof(sctx)); + memset(&apdu, 0, sizeof(apdu)); + + switch (pin_id) { + case PACE_MRZ: + case PACE_CAN: + case PACE_PIN: + case PACE_PUK: + break; + default: + sc_error(card->ctx, "Type of secret not supported"); + return SC_ERROR_INVALID_ARGUMENTS; + } + + if (pinlen > sizeof(buf) - 5) { + sc_error(card->ctx, "%s too long (maximal %u bytes supported)", + pace_secret_name(pin_id), + sizeof(buf) - 5); + } + buf[0] = pin_id; + buf[1] = 0; // length_chat + buf[2] = pinlen; // length_pin + memcpy(&buf[3], pin, pinlen); + buf[3 + pinlen] = 0; // length_cert_desc + buf[4 + pinlen]= 0; // length_cert_desc + + SC_TEST_RET(card->ctx, + EstablishPACEChannel(card, buf, &out, &outlen, &sctx), + "Could not establish PACE channel."); + + printf("Established PACE channel.\n"); + + if (new_pin_id) { + SC_TEST_RET(card->ctx, + pace_change_p(&sctx, card, new_pin_id, new_pin, new_pinlen), + "Could not change PACE secret."); + } else { + while (1) { + printf("Enter unencrypted APDU (empty line to exit)\n"); + + linelen = getline(&read, &readlen, stdin); + if (linelen <= 1) { + if (linelen < 0) { + r = SC_ERROR_INTERNAL; + sc_error(card->ctx, "Could not read line"); + } else { + r = SC_SUCCESS; + printf("Thanks for flying with ccid\n"); + } + break; + } + + read[linelen - 1] = 0; + if (sc_hex_to_bin(read, buf, &apdulen) < 0) { + sc_error(card->ctx, "Could not format binary string"); + } + + r = build_apdu(card->ctx, buf, apdulen, &apdu); + if (r < 0) { + sc_error(card->ctx, "Could not format APDU"); + continue; + } + + apdu.resp = buf; + apdu.resplen = sizeof(buf); + + r = pace_transmit_apdu(&sctx, card, &apdu); + if (r < 0) { + sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r)); + continue; + } + + printf("Decrypted APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2); + bin_print(stdout, "Decrypted APDU response data", apdu.resp, apdu.resplen); + } + + if (read) + free(read); + } + + SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); } int @@ -171,11 +285,24 @@ main (int argc, char **argv) return 1; } - i = testpace(pin_id, pin, !pin ? 0 : strlen(pin), + 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); + break; + } + } + if (i == SC_MAX_SLOTS) { + perror("No card found"); + sc_disconnect_card(card, 0); + sc_release_context(ctx); + return 1; + } + + i = pace_test(card, pin_id, pin, !pin ? 0 : strlen(pin), dochangepin, newpin, !newpin ? 0 : strlen(newpin)); - if (ctx) - sc_release_context(ctx); + sc_disconnect_card(card, 0); + sc_release_context(ctx); return i; } diff --git a/ccid/pace.c b/ccid/pace.c index 1bf73a9..5a34ec7 100644 --- a/ccid/pace.c +++ b/ccid/pace.c @@ -31,9 +31,6 @@ #include #include #include -#include -#include -#include #include @@ -530,7 +527,7 @@ err: SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); } -static int +int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id, const char *new, size_t new_len) { @@ -839,100 +836,6 @@ const char *pace_secret_name(enum s_type pin_id) { } } -int pace_test(sc_card_t *card, - enum s_type pin_id, const char *pin, size_t pinlen, - enum s_type new_pin_id, const char *new_pin, size_t new_pinlen) -{ - u8 buf[0xff + 5]; - char *read = NULL; - __u8 *out = NULL; - size_t outlen, readlen = 0, apdulen; - ssize_t linelen; - struct sm_ctx sctx; - sc_apdu_t apdu; - int r; - - memset(&sctx, 0, sizeof(sctx)); - memset(&apdu, 0, sizeof(apdu)); - - switch (pin_id) { - case PACE_MRZ: - case PACE_CAN: - case PACE_PIN: - case PACE_PUK: - break; - default: - sc_error(card->ctx, "Type of secret not supported"); - return SC_ERROR_INVALID_ARGUMENTS; - } - - if (pinlen > sizeof(buf) - 5) { - sc_error(card->ctx, "%s too long (maximal %u bytes supported)", - pace_secret_name(pin_id), - sizeof(buf) - 5); - } - buf[0] = pin_id; - buf[1] = 0; // length_chat - buf[2] = pinlen; // length_pin - memcpy(&buf[3], pin, pinlen); - buf[3 + pinlen] = 0; // length_cert_desc - buf[4 + pinlen]= 0; // length_cert_desc - - SC_TEST_RET(card->ctx, - EstablishPACEChannel(card, buf, &out, &outlen, &sctx), - "Could not establish PACE channel."); - - if (new_pin_id) { - SC_TEST_RET(card->ctx, - pace_change_p(&sctx, card, new_pin_id, new_pin, new_pinlen), - "Could not change PACE secret."); - } - - while (1) { - printf("Enter unencrypted APDU (empty line to exit)\n"); - - linelen = getline(&read, &readlen, stdin); - if (linelen <= 1) { - if (linelen < 0) { - r = SC_ERROR_INTERNAL; - sc_error(card->ctx, "Could not read line"); - } else { - r = SC_SUCCESS; - printf("Thanks for flying with ccid\n"); - } - break; - } - - read[linelen - 1] = 0; - if (sc_hex_to_bin(read, buf, &apdulen) < 0) { - sc_error(card->ctx, "Could not format binary string"); - } - - r = build_apdu(card->ctx, buf, apdulen, &apdu); - if (r < 0) { - sc_error(card->ctx, "Could not format APDU"); - continue; - } - - apdu.resp = buf; - apdu.resplen = sizeof(buf); - - r = pace_transmit_apdu(&sctx, card, &apdu); - if (r < 0) { - sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r)); - continue; - } - - printf("Decrypted APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2); - bin_print(stdout, "Decrypted APDU response data", apdu.resp, apdu.resplen); - } - - if (read) - free(read); - - SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); -} - static int encode_ssc(const BIGNUM *ssc, const PACE_CTX *ctx, u8 **encoded) { @@ -1325,37 +1228,3 @@ int pace_transmit_apdu(struct sm_ctx *ctx, sc_card_t *card, SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); } - -int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id, - const char *newp, size_t newplen) -{ - sc_ui_hints_t hints; - char *p = NULL; - int r; - - if (!newplen || !newp) { - memset(&hints, 0, sizeof(hints)); - hints.dialog_name = "ccid.PACE"; - hints.card = card; - hints.prompt = NULL; - hints.obj_label = pace_secret_name(pin_id); - hints.usage = SC_UI_USAGE_NEW_PIN; - r = sc_ui_get_pin(&hints, &p); - if (r < 0) { - sc_error(card->ctx, "Could not read new %s (%s).\n", - hints.obj_label, sc_strerror(r)); - SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r); - } - newplen = strlen(p); - newp = p; - } - - r = pace_reset_retry_counter(ctx, card, pin_id, newp, newplen); - - if (p) { - OPENSSL_cleanse(p, newplen); - free(p); - } - - SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r); -} diff --git a/ccid/pace.h b/ccid/pace.h index 61b0212..0317fde 100644 --- a/ccid/pace.h +++ b/ccid/pace.h @@ -63,18 +63,11 @@ int GetReadersPACECapabilities(sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen); int EstablishPACEChannel(sc_card_t *card, const __u8 *in, __u8 **out, size_t *outlen, struct sm_ctx *ctx); -int pace_test(sc_card_t *card, - enum s_type pin_id, const char *pin, size_t pinlen, - enum s_type new_pin_id, const char *new_pin, size_t new_pinlen); -int pace_change_p(struct sm_ctx *ctx, sc_card_t *card, enum s_type pin_id, - const char *newp, size_t newplen); -#define pace_change_pin(ctx, card, newpin, newpinlen) \ - pace_change_p(ctx, card, PACE_PIN, newpin, newpinlen) -#define pace_change_can(ctx, card, newcan, newcanlen) \ - pace_change_p(ctx, card, PACE_CAN, newcan, newcanlen) int pace_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card, sc_apdu_t *apdu); +int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card, + enum s_type pin_id, const char *new, size_t new_len); #ifdef __cplusplus }