diff --git a/ccid/configure.ac b/ccid/configure.ac index 1202ed4..22557dc 100644 --- a/ccid/configure.ac +++ b/ccid/configure.ac @@ -99,6 +99,7 @@ LIBS="$saved_LIBS" AM_CONDITIONAL(WITH_PACE, test "${enable_pace}" != "no") AM_COND_IF(WITH_PACE, [AC_DEFINE(WITH_PACE, 1, [enable PACE support])]) AM_COND_IF(WITH_PACE, [AC_DEFINE(BUERGERCLIENT_WORKAROUND, 1, [Always get EF.CardAccess, when connecting to a smart card. This is a workaround for the recent Buergerclient])]) +#AM_COND_IF(WITH_PACE, [AC_DEFINE(MODIFY_PIN, 1, [Change the PIN after authentication.])]) # --disable-cats diff --git a/ccid/src/Makefile.am b/ccid/src/Makefile.am index 2987586..2089f9a 100644 --- a/ccid/src/Makefile.am +++ b/ccid/src/Makefile.am @@ -2,7 +2,7 @@ EXTRA_DIST = $(shell find $(top_srcdir)/src/opensc -path '*/.svn' -prune -o -typ AM_CPPFLAGS = -I$(top_srcdir)/src/opensc/src -ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c +ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c sslutil.c ccid_emulator_LDADD = $(OPENSSL_LIBS) $(PTHREAD_LIBS) ccid_emulator_CFLAGS = $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS) @@ -18,6 +18,7 @@ noinst_HEADERS = \ pcscutil.h \ scutil.h \ ccid.h \ + sslutil.h \ usbstring.h if WITH_CCID diff --git a/ccid/src/cats-test.c b/ccid/src/cats-test.c index 6c2df67..8dcd577 100644 --- a/ccid/src/cats-test.c +++ b/ccid/src/cats-test.c @@ -186,7 +186,7 @@ main(int argc, char *argv[]) SCARDHANDLE hCard; LPSTR readers = NULL; BYTE sendbuf[16], recvbuf[1024]; - DWORD ctl, recvlen, protocol; + DWORD pace_ctl, modify_ctl, recvlen, protocol; time_t t_start, t_end; size_t l, pinlen = 0; char *pin = NULL; @@ -275,25 +275,28 @@ main(int argc, char *argv[]) goto err; } - ctl = 0; + pace_ctl = 0; for (i = 0; i <= recvlen-PCSC_TLV_ELEMENT_SIZE; i += PCSC_TLV_ELEMENT_SIZE) { if (recvbuf[i] == FEATURE_EXECUTE_PACE) { - memcpy(&ctl, recvbuf+i+2, 4); - break; + memcpy(&pace_ctl, recvbuf+i+2, 4); + } + if (recvbuf[i] == FEATURE_MODIFY_PIN_DIRECT) { + memcpy(&modify_ctl, recvbuf+i+2, 4); } } - if (0 == ctl) { + if (0 == pace_ctl) { printf("Reader does not support PACE\n"); goto err; } /* convert to host byte order to use for SCardControl */ - ctl = ntohl(ctl); + pace_ctl = ntohl(pace_ctl); + modify_ctl = ntohl(modify_ctl); recvlen = sizeof(recvbuf); sendbuf[0] = 0x01; /* idxFunction = GetReadersPACECapabilities */ sendbuf[1] = 0x00; /* lengthInputData */ sendbuf[2] = 0x00; /* lengthInputData */ - r = SCardControl(hCard, ctl, + r = SCardControl(hCard, pace_ctl, sendbuf, 3, recvbuf, sizeof(recvbuf), &recvlen); if (r != SCARD_S_SUCCESS) { @@ -314,7 +317,7 @@ main(int argc, char *argv[]) sendbuf[6+pinlen] = 0x00; /* length certificate description */ sendbuf[7+pinlen] = 0x00; /* length certificate description */ t_start = time(NULL); - r = SCardControl(hCard, ctl, + r = SCardControl(hCard, pace_ctl, sendbuf, 8+pinlen, recvbuf, sizeof(recvbuf), &recvlen); t_end = time(NULL); @@ -391,6 +394,20 @@ main(int argc, char *argv[]) } #endif +#ifdef MODIFY_PIN + if (0 == modify_ctl) { + printf("Reader does not support MODIFY_PIN_DIRECT\n"); + goto err; + } + + BYTE = bufs2[] = {0x15, 0x05, 0x82, 0x08, 0x00, 0x00, 0x00, 0x06, 0x06, + 0x01, 0x02, 0x02, 0x09, 0x04, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x2C, 0x02, 0x03, 0x00}; + recvlen = sizeof(recvbuf); + rv = SCardControl(hCard, modify_ioctl, bufs2, + sizeof bufs2, recvbuf, sizeof recvbuf, &recvlen); +#endif + err: stringify_error(r); pcsc_disconnect(hContext, hCard, readers); diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c index 3c893c6..be549e6 100644 --- a/ccid/src/ccid.c +++ b/ccid/src/ccid.c @@ -27,6 +27,7 @@ #include #include "ccid.h" +#include "sslutil.h" #include "config.h" #ifdef WITH_PACE @@ -48,12 +49,14 @@ static sc_context_t *ctx = NULL; static sc_card_t *card = NULL; static sc_reader_t *reader = NULL; +unsigned int skipfirst = 0; + struct ccid_class_descriptor ccid_desc = { .bLength = sizeof ccid_desc, .bDescriptorType = 0x21, .bcdCCID = __constant_cpu_to_le16(0x0110), - .bMaxSlotIndex = 1, + .bMaxSlotIndex = 0, .bVoltageSupport = 0x01, // 5.0V .dwProtocols = __constant_cpu_to_le32( 0x01| // T=0 @@ -242,7 +245,12 @@ static __u8 get_bStatus(int sc_result) int flags; __u8 bstatus = 0; - flags = detect_card_presence(); + if (skipfirst > 10) + flags = detect_card_presence(); + else { + skipfirst += 1; + flags = SC_SUCCESS; + } if (flags >= 0) { if (sc_result < 0) { @@ -435,8 +443,8 @@ perform_PC_to_RDR_IccPowerOff(const __u8 *in, size_t inlen, __u8 **out, size_t * || request->abRFU2 != 0) sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: malformed PC_to_RDR_IccPowerOff"); - sc_reset(card, 1); - sc_result = sc_disconnect_card(card); + //sc_reset(card, 1); + //sc_result = sc_disconnect_card(card); return get_RDR_to_PC_SlotStatus(request->bSeq, sc_result, out, outlen, NULL, 0); @@ -689,8 +697,7 @@ write_pin_length(sc_apdu_t *apdu, const struct sc_pin_cmd_pin *pin, if (!apdu || !apdu->data || !pin || apdu->datalen <= pin->length_offset || !sc_result) { - if (sc_result) - *sc_result = SC_ERROR_INVALID_ARGUMENTS; + *sc_result = SC_ERROR_INVALID_ARGUMENTS; return 0; } @@ -1112,6 +1119,7 @@ static int perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outlen) { int sc_result; + u8 curr_pin_data[0xff], new_pin_data[0xff]; struct sc_pin_cmd_pin curr_pin, new_pin; sc_apdu_t apdu; const PC_to_RDR_Secure_t *request = (PC_to_RDR_Secure_t *) in; @@ -1123,6 +1131,12 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle memset(&curr_pin, 0, sizeof(curr_pin)); memset(&new_pin, 0, sizeof(new_pin)); + memset(curr_pin_data, 0, sizeof curr_pin_data); + memset(new_pin_data, 0, sizeof new_pin_data); + curr_pin.data = curr_pin_data; + curr_pin.len = sizeof curr_pin_data; + new_pin.data = new_pin_data; + new_pin.len = sizeof new_pin_data; if (!in || !out || !outlen) @@ -1225,6 +1239,12 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle new_pin.min_length = curr_pin.min_length = wPINMaxExtraDigit >> 8; new_pin.min_length = curr_pin.max_length = wPINMaxExtraDigit & 0x00ff; + if (new_pin.min_length > new_pin.max_length) { + /* If maximum length is smaller than minimum length, suppose minimum + * length defines the exact length of the pin. */ + curr_pin.max_length = curr_pin.min_length; + new_pin.max_length = new_pin.min_length; + } uint8_t system_units = bmFormatString & CCID_PIN_UNITS_BYTES; uint8_t pin_offset = (bmFormatString >> 3) & 0xf; uint8_t length_offset = bmPINLengthFormat & 0xf; @@ -1259,6 +1279,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle 0)) { sc_result = SC_ERROR_INTERNAL; sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read PIN.\n"); + ssl_error(ctx); goto err; } } else { @@ -1270,6 +1291,7 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle 0)) { sc_result = SC_ERROR_INTERNAL; sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read current PIN.\n"); + ssl_error(ctx); goto err; } } @@ -1280,6 +1302,10 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle modify->bConfirmPIN & CCID_PIN_CONFIRM_NEW)) { sc_result = SC_ERROR_INTERNAL; sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not read new PIN.\n"); + sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "min %d max %d confirm %d.\n", + new_pin.min_length, new_pin.max_length, modify->bConfirmPIN + & CCID_PIN_CONFIRM_NEW); + ssl_error(ctx); goto err; } } @@ -1321,14 +1347,8 @@ perform_PC_to_RDR_Secure(const __u8 *in, size_t inlen, __u8** out, size_t *outle sc_mem_clear((u8 *) apdu.data, apdu.datalen); err: - if (curr_pin.data) { - sc_mem_clear((u8 *) curr_pin.data, curr_pin.len); - free((u8 *) curr_pin.data); - } - if (new_pin.data) { - sc_mem_clear((u8 *) new_pin.data, new_pin.len); - free((u8 *) new_pin.data); - } + sc_mem_clear((u8 *) curr_pin.data, curr_pin.len); + sc_mem_clear((u8 *) new_pin.data, new_pin.len); sc_result = get_RDR_to_PC_DataBlock(request->bSeq, sc_result, out, outlen, abDataOut, abDataOutLen); diff --git a/ccid/src/sslutil.c b/ccid/src/sslutil.c new file mode 120000 index 0000000..6f3af05 --- /dev/null +++ b/ccid/src/sslutil.c @@ -0,0 +1 @@ +../../npa/src/sslutil.c \ No newline at end of file diff --git a/ccid/src/sslutil.h b/ccid/src/sslutil.h new file mode 120000 index 0000000..ae68de1 --- /dev/null +++ b/ccid/src/sslutil.h @@ -0,0 +1 @@ +../../npa/src/sslutil.h \ No newline at end of file diff --git a/npa/src/Makefile.am b/npa/src/Makefile.am index b72569d..c69dc18 100644 --- a/npa/src/Makefile.am +++ b/npa/src/Makefile.am @@ -2,7 +2,7 @@ EXTRA_DIST = $(shell find $(top_srcdir)/src/opensc -path '*/.svn' -prune -o -typ AM_CPPFLAGS = -I$(top_srcdir)/src/npa -I$(top_srcdir)/src/opensc/src -libnpa_la_SOURCES = sm.c scutil.c npa.c +libnpa_la_SOURCES = sm.c scutil.c npa.c sslutil.c libnpa_la_LIBADD = $(OPENSSL_LIBS) $(OPENSC_LIBS) libnpa_la_CFLAGS = $(OPENSSL_CFLAGS) @@ -16,6 +16,7 @@ bin_PROGRAMS = npa-tool lib_LTLIBRARIES = libnpa.la noinst_HEADERS = \ + sslutil.h \ binutil.h nobase_include_HEADERS = \ diff --git a/npa/src/npa.c b/npa/src/npa.c index 6a68eac..ba10c4a 100644 --- a/npa/src/npa.c +++ b/npa/src/npa.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Frank Morgner + * Copyright (C) 2011 Frank Morgner * * This file is part of ccid. * @@ -19,6 +19,7 @@ #include "npa.h" #include "sm.h" #include "scutil.h" +#include "sslutil.h" #include #include #include @@ -906,15 +907,6 @@ get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id return r; } -void ssl_error(sc_context_t *ctx) { - unsigned long r; - ERR_load_crypto_strings(); - for (r = ERR_get_error(); r; r = ERR_get_error()) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, ERR_error_string(r, NULL)); - } - ERR_free_strings(); -} - int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card, struct establish_pace_channel_input pace_input, struct establish_pace_channel_output *pace_output, diff --git a/npa/src/sslutil.c b/npa/src/sslutil.c new file mode 100644 index 0000000..a3ed1c8 --- /dev/null +++ b/npa/src/sslutil.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 Frank Morgner + * + * This file is part of ccid. + * + * ccid is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * ccid 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * ccid. If not, see . + */ +#include "sslutil.h" +#include +#include + +void ssl_error(sc_context_t *ctx) { + unsigned long r; + ERR_load_crypto_strings(); + for (r = ERR_get_error(); r; r = ERR_get_error()) { + sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, ERR_error_string(r, NULL)); + } + ERR_free_strings(); +} diff --git a/npa/src/sslutil.h b/npa/src/sslutil.h new file mode 100644 index 0000000..739f7ff --- /dev/null +++ b/npa/src/sslutil.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2011 Frank Morgner + * + * This file is part of ccid. + * + * ccid is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * ccid 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * ccid. If not, see . + */ +#ifndef _CCID_SSLUTIL_H +#define _CCID_SSLUTIL_H + +#include + +void ssl_error(sc_context_t *ctx); + +#endif