diff --git a/doc/tools/opensc-explorer.1.xml b/doc/tools/opensc-explorer.1.xml
index 56c0b25a..6e981efb 100644
--- a/doc/tools/opensc-explorer.1.xml
+++ b/doc/tools/opensc-explorer.1.xml
@@ -475,22 +475,6 @@
-
-
- pace secret-type [secret]
-
- Perform PACE with the card. secret-type
- can be one of pin, can, puk or mrz. secret is the secret to be verified as string.
-
-
- If secret is omitted, the secret will be verified with the PIN-Pad.
-
-
- Example: pace can 123456
-
-
-
-
diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am
index f9fa033d..06689de0 100644
--- a/src/libopensc/Makefile.am
+++ b/src/libopensc/Makefile.am
@@ -10,7 +10,8 @@ noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem.
opensc.h pkcs15.h \
cardctl.h asn1.h log.h \
errors.h types.h compression.h itacns.h iso7816.h \
- authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h
+ authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \
+ pace.h
AM_CPPFLAGS = -DOPENSC_CONF_PATH=\"$(sysconfdir)/opensc.conf\"
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_OPENCT_CFLAGS) \
diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports
index d3e38fa5..4d3de66d 100644
--- a/src/libopensc/libopensc.exports
+++ b/src/libopensc/libopensc.exports
@@ -302,7 +302,6 @@ sc_remote_data_init
sc_crc32
sc_pkcs15_convert_prkey
sc_pkcs15_convert_pubkey
-sc_perform_pace
iasecc_sdo_encode_update_field
iasecc_sm_create_file
iasecc_sm_delete_file
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
index c6bcf432..878f8210 100644
--- a/src/libopensc/opensc.h
+++ b/src/libopensc/opensc.h
@@ -330,7 +330,7 @@ struct sc_pin_cmd_pin {
u8 pad_char;
size_t offset; /* PIN offset in the APDU */
size_t length_offset; /* Effective PIN length offset in the APDU */
-
+
int max_tries; /* Used for signaling back from SC_PIN_CMD_GET_INFO */
int tries_left; /* Used for signaling back from SC_PIN_CMD_GET_INFO */
@@ -349,7 +349,7 @@ struct sc_pin_cmd_data {
struct sc_apdu *apdu; /* APDU of the PIN command */
};
-
+#if 0
#define PACE_PIN_ID_MRZ 0x01
#define PACE_PIN_ID_CAN 0x02
#define PACE_PIN_ID_PIN 0x03
@@ -414,6 +414,7 @@ struct establish_pace_channel_output {
/** PCD identifier */
unsigned char *id_pcd;
};
+#endif
struct sc_reader_operations {
/* Called during sc_establish_context(), when the driver
@@ -442,11 +443,12 @@ struct sc_reader_operations {
int (*display_message)(struct sc_reader *, const char *);
int (*perform_verify)(struct sc_reader *, struct sc_pin_cmd_data *);
int (*perform_pace)(struct sc_reader *reader,
- struct establish_pace_channel_input *,
- struct establish_pace_channel_output *);
+ void *establish_pace_channel_input,
+ void *establish_pace_channel_output);
/* Wait for an event */
- int (*wait_for_event)(struct sc_context *ctx, unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event,
+ int (*wait_for_event)(struct sc_context *ctx, unsigned int event_mask,
+ sc_reader_t **event_reader, unsigned int *event,
int timeout, void **reader_states);
/* Reset a reader */
int (*reset)(struct sc_reader *, int);
@@ -1294,10 +1296,6 @@ extern const char *sc_get_version(void);
extern sc_card_driver_t *sc_get_iso7816_driver(void);
-int sc_perform_pace(sc_card_t *card,
- struct establish_pace_channel_input *pace_input,
- struct establish_pace_channel_output *pace_output);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/libopensc/pace.h b/src/libopensc/pace.h
new file mode 100644
index 00000000..c499b958
--- /dev/null
+++ b/src/libopensc/pace.h
@@ -0,0 +1,107 @@
+/*
+ * opensc.h: PACE library header file
+ *
+ * Copyright (C) ???? Frank Morgner
+ *
+ * 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
+ */
+
+#ifndef _PACE_H
+#define _PACE_H
+
+#include
+#ifdef HAVE_UNISTD_H
+#include
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "libopensc/opensc.h"
+#ifdef ENABLE_SM
+#include "libopensc/sm.h"
+#endif
+
+#define PACE_PIN_ID_MRZ 0x01
+#define PACE_PIN_ID_CAN 0x02
+#define PACE_PIN_ID_PIN 0x03
+#define PACE_PIN_ID_PUK 0x04
+/**
+ * Input data for EstablishPACEChannel()
+ */
+struct establish_pace_channel_input {
+ /** Type of secret (CAN, MRZ, PIN or PUK). */
+ unsigned char pin_id;
+
+ /** Length of \a chat */
+ size_t chat_length;
+ /** Card holder authorization template */
+ const unsigned char *chat;
+
+ /** Length of \a pin */
+ size_t pin_length;
+ /** Secret */
+ const unsigned char *pin;
+
+ /** Length of \a certificate_description */
+ size_t certificate_description_length;
+ /** Certificate description */
+ const unsigned char *certificate_description;
+};
+
+/**
+ * Output data for EstablishPACEChannel()
+ */
+struct establish_pace_channel_output {
+ /** PACE result (TR-03119) */
+ unsigned int result;
+
+ /** MSE: Set AT status byte */
+ unsigned char mse_set_at_sw1;
+ /** MSE: Set AT status byte */
+ unsigned char mse_set_at_sw2;
+
+ /** Length of \a ef_cardaccess */
+ size_t ef_cardaccess_length;
+ /** EF.CardAccess */
+ unsigned char *ef_cardaccess;
+
+ /** Length of \a recent_car */
+ size_t recent_car_length;
+ /** Most recent certificate authority reference */
+ unsigned char *recent_car;
+
+ /** Length of \a previous_car */
+ size_t previous_car_length;
+ /** Previous certificate authority reference */
+ unsigned char *previous_car;
+
+ /** Length of \a id_icc */
+ size_t id_icc_length;
+ /** ICC identifier */
+ unsigned char *id_icc;
+
+ /** Length of \a id_pcd */
+ size_t id_pcd_length;
+ /** PCD identifier */
+ unsigned char *id_pcd;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c
index 3b3877b7..920b6f11 100644
--- a/src/libopensc/reader-pcsc.c
+++ b/src/libopensc/reader-pcsc.c
@@ -37,6 +37,8 @@
#include "internal.h"
#include "internal-winscard.h"
+#include "pace.h"
+
/* Logging */
#define PCSC_TRACE(reader, desc, rv) do { sc_log(reader->ctx, "%s:" desc ": 0x%08lx\n", reader->name, rv); } while (0)
#define PCSC_LOG(ctx, desc, rv) do { sc_log(ctx, desc ": 0x%08lx\n", rv); } while (0)
@@ -1898,13 +1900,15 @@ static int transform_pace_output(u8 *rbuf, size_t rbuflen,
return SC_SUCCESS;
}
-static int pcsc_perform_pace(struct sc_reader *reader,
- struct establish_pace_channel_input *pace_input,
- struct establish_pace_channel_output *pace_output)
+
+static int
+pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace)
{
+ struct establish_pace_channel_input *pace_input = (struct establish_pace_channel_input *) input_pace;
+ struct establish_pace_channel_output *pace_output = (struct establish_pace_channel_output *) output_pace;
struct pcsc_private_data *priv;
u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE], sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE];
- size_t rcount = sizeof rbuf, scount = sizeof sbuf;
+ size_t rcount = sizeof rbuf, scount = sizeof sbuf;
if (!reader || !reader->capabilities & SC_READER_CAP_PACE_GENERIC)
return SC_ERROR_INVALID_ARGUMENTS;
diff --git a/src/libopensc/sec.c b/src/libopensc/sec.c
index a1e06043..1244e857 100644
--- a/src/libopensc/sec.c
+++ b/src/libopensc/sec.c
@@ -279,127 +279,3 @@ int sc_build_pin(u8 *buf, size_t buflen, struct sc_pin_cmd_pin *pin, int pad)
return i;
}
-
-int sc_perform_pace(sc_card_t *card,
- struct establish_pace_channel_input *pace_input,
- struct establish_pace_channel_output *pace_output)
-{
- int r = SC_ERROR_NOT_SUPPORTED;
- u8 buf[0xffff];
-
- assert(card != NULL && pace_input != NULL && pace_output != NULL);
- SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
-
- switch (pace_input->pin_id) {
- case PACE_PIN_ID_MRZ:
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Initiating PACE with MRZ");
- break;
- case PACE_PIN_ID_CAN:
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Initiating PACE with CAN");
- break;
- case PACE_PIN_ID_PIN:
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Initiating PACE with PIN");
- break;
- case PACE_PIN_ID_PUK:
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Initiating PACE with PUK");
- break;
- default:
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Initiating PACE with unknown PACE secret type");
- break;
- }
-
- if (pace_input->chat_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_input->chat,
- pace_input->chat_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "CHAT (%d bytes):\n%s",
- pace_input->chat_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "CHAT (0 bytes)");
- }
-
- if (pace_input->certificate_description_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_input->certificate_description,
- pace_input->certificate_description_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Certificate description (%d bytes):\n%s",
- pace_input->certificate_description_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Certificate description (0 bytes)");
- }
-
- if (card->reader
- && card->reader->ops
- && card->reader->ops->perform_pace
- && card->reader->capabilities & SC_READER_CAP_PACE_GENERIC) {
- r = card->reader->ops->perform_pace(card->reader, pace_input,
- pace_output);
- } else {
- /* TODO Add EstablishPACEChannel using a normal reader here */
- /* see for example http://vsmartcard.sourceforge.net/npa/README.html */
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "PACE currently only supported via reader.");
- }
-
- sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
- "EstablishPACEChannel Result is 0x%08X",
- pace_output->result);
-
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "MSE:Set AT Statusbytes: %02X %02X",
- pace_output->mse_set_at_sw1, pace_output->mse_set_at_sw2);
-
-
- if (pace_output->ef_cardaccess_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_output->ef_cardaccess,
- pace_output->ef_cardaccess_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "EF.CardAccess (%d bytes):\n%s",
- pace_output->ef_cardaccess_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "EF.CardAccess (0 bytes)");
- }
-
- if (pace_output->recent_car_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_output->recent_car,
- pace_output->recent_car_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Most recent certificate authority reference (%d bytes):\n%s",
- pace_output->recent_car_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Most recent certificate authority reference (0 bytes)");
- }
-
- if (pace_output->previous_car_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_output->previous_car,
- pace_output->previous_car_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Previous certificate authority reference (%d bytes):\n%s",
- pace_output->previous_car_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Previous certificate authority reference (0 bytes)");
- }
-
- if (pace_output->id_icc_length) {
- sc_hex_dump(card->ctx, SC_LOG_DEBUG_NORMAL,
- pace_output->id_icc,
- pace_output->id_icc_length, buf, sizeof buf);
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Ephemeral PACE public key of the ICC (ID ICC, %d bytes):\n%s",
- pace_output->id_icc_length, buf);
- } else {
- sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
- "Ephemeral PACE public key of the ICC (ID ICC, 0 bytes)");
- }
-
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
-}
diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c
index 84fc4ad0..ef2f3f32 100644
--- a/src/tools/opensc-explorer.c
+++ b/src/tools/opensc-explorer.c
@@ -92,7 +92,6 @@ static int do_create(int argc, char **argv);
static int do_mkdir(int argc, char **argv);
static int do_delete(int argc, char **argv);
static int do_verify(int argc, char **argv);
-static int do_pace(int argc, char **argv);
static int do_change(int argc, char **argv);
static int do_unblock(int argc, char **argv);
static int do_get(int argc, char **argv);
@@ -151,9 +150,6 @@ static struct command cmds[] = {
{ do_verify,
"verify", "{CHV|KEY|AUT|PRO} []",
"present a PIN or key to the card" },
- { do_pace,
- "pace", "{pin|can|puk|mrz} []",
- "Establish a PACE channel" },
{ do_change,
"change", "CHV [[] ]",
"change a PIN" },
@@ -1032,46 +1028,6 @@ static int do_verify(int argc, char **argv)
return 0;
}
-
-static int do_pace(int argc, char **argv)
-{
- int r;
- struct establish_pace_channel_input pace_input;
- struct establish_pace_channel_output pace_output;
- memset(&pace_input, 0, sizeof(pace_input));
- memset(&pace_output, 0, sizeof(pace_output));
-
- switch (argc) {
- case 2:
- pace_input.pin = (unsigned char *) argv[1];
- /* fall through */
- case 1:
- if (strcasecmp(argv[0], "pin") == 0)
- pace_input.pin_id = PACE_PIN_ID_PIN;
- else if (strcasecmp(argv[0], "puk") == 0)
- pace_input.pin_id = PACE_PIN_ID_PUK;
- else if (strcasecmp(argv[0], "can") == 0)
- pace_input.pin_id = PACE_PIN_ID_CAN;
- else if (strcasecmp(argv[0], "mrz") == 0)
- pace_input.pin_id = PACE_PIN_ID_MRZ;
- else
- return usage(do_pace);
- break;
- default:
- return usage(do_pace);
- }
-
- r = sc_perform_pace(card, &pace_input, &pace_output);
- if (r) {
- printf("PACE failed: %s\n", sc_strerror(r));
- return -1;
- }
- printf("Established PACE channel.\n");
-
- return 0;
-}
-
-
static int do_change(int argc, char **argv)
{
int ref, r, tries_left = -1;