From 41861e42b01539856b31f758dfde9ba53749eaaa Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 26 Aug 2012 11:16:30 +0200 Subject: [PATCH] no 'pace' in common part 'PACE' is extremely card specific protocol and has not to be ostensibly present in the common part of OpenSC: * currently in OpenSC there is no card driver that supports or uses this protocol; * amazing content of the common 'sc_perform_pace' -- beside the verbose logs the only substantial action is to call the card/reader specific handler. According to the current sources and the pull request 83 this 'common' procedure is called by the card driver or card specific tool/operation. * currently the 'PACE' can be thouroghly tested only by one person (Frank Morgner), and only using the OpenSSL patched with the PACE specific patch. So, at least a dedicated configuration option could be introduced when comiting PACE to the common part. * common 'sc_perfom_pace' has the same role as the 'initialize-SM' handler of the existing SM framework and can be implemented as card specific SM, as the others cards do. This confirmed by Frank Morgner, the author of PACE commits and nPA card driver, himself. (https://github.com/OpenSC/OpenSC/pull/83) --- doc/tools/opensc-explorer.1.xml | 16 ----- src/libopensc/Makefile.am | 3 +- src/libopensc/libopensc.exports | 1 - src/libopensc/opensc.h | 16 ++--- src/libopensc/pace.h | 107 +++++++++++++++++++++++++++ src/libopensc/reader-pcsc.c | 12 ++-- src/libopensc/sec.c | 124 -------------------------------- src/tools/opensc-explorer.c | 44 ------------ 8 files changed, 124 insertions(+), 199 deletions(-) create mode 100644 src/libopensc/pace.h 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;