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
}