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;